diff options
82 files changed, 10257 insertions, 84 deletions
| @@ -2,6 +2,12 @@  Changes since for U-Boot 0.1.0:  ====================================================================== +* Patch by Daniel Engström, 13 Nov 2002: +  Add support for i386 architecture and AMD SC520 board + +* Patch by Pierre Aubert, 12 Nov 2002: +  Add support for DOS filesystem and booting from DOS floppy disk +  * Patch by Jim Sandoz, 07 Nov 2002:    Increase number of network RX buffers (PKTBUFSRX in    "include/net.h") for EEPRO100 based boards (especially SP8240) @@ -83,6 +83,10 @@ N: Dave Ellis  E: DGE@sixnetio.com  D: EEPROM Speedup, SXNI855T port +N: Daniel Engström +E: daniel@omicron.se +D: x86 port, Support for sc520_cdp board +  N: Dr. Wolfgang Grandegger  E: wg@denx.de  D: Support for Interphase 4539 T1/E1/J1 PMC, PN62, CCM, SCM boards diff --git a/MAINTAINERS b/MAINTAINERS index ca5c78eb7..c924c6540 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -250,5 +250,16 @@ Alex Züpke <azu@sysgo.de>  	dnp1110			SA1110  ######################################################################### +# x86 Systems:								# +#									# +# Maintainer Name, Email Address					# +#	Board			CPU					# +######################################################################### + +Daniel Engström <daniel@omicron.se> + +	sc520_cdp		x86 + +#########################################################################  # End of MAINTAINERS list						#  ######################################################################### @@ -74,6 +74,9 @@ endif  ifeq ($(ARCH),arm)  CROSS_COMPILE = arm_920TDI-  endif +ifeq ($(ARCH),i386) +#CROSS_COMPILE = i386-elf- +endif  endif  endif @@ -100,7 +103,10 @@ SUBDIRS	= tools \  # U-Boot objects....order is important (i.e. start must be first)  OBJS  =	cpu/$(CPU)/start.o - +ifeq ($(CPU),i386) +OBJS +=	cpu/$(CPU)/start16.o +OBJS +=	cpu/$(CPU)/reset.o +endif  ifeq ($(CPU),ppc4xx)  OBJS +=	cpu/$(CPU)/resetvec.o  endif @@ -108,7 +114,7 @@ endif  LIBS  =	board/$(BOARDDIR)/lib$(BOARD).a  LIBS += cpu/$(CPU)/lib$(CPU).a  LIBS += lib_$(ARCH)/lib$(ARCH).a -LIBS += fs/jffs2/libjffs2.a +LIBS += fs/jffs2/libjffs2.a fs/fdos/libfdos.a  LIBS += net/libnet.a  LIBS += disk/libdisk.a  LIBS += rtc/librtc.a @@ -627,6 +633,15 @@ cradle_config	:	unconfig  csb226_config	:	unconfig  	@./mkconfig $(@:_config=) arm xscale csb226 +#======================================================================== +# i386 +#======================================================================== +######################################################################### +## AMD SC520 CDP  +######################################################################### +sc520_cdp_config	:	unconfig +	@./mkconfig $(@:_config=) i386 i386 sc520_cdp +  #########################################################################  clean: @@ -536,6 +536,7 @@ The following options need to be configured:  		CFG_CMD_ELF	  bootelf, bootvx  		CFG_CMD_ENV	  saveenv  		CFG_CMD_FDC	* Floppy Disk Support +		CFG_CMD_FDOS	* Dos diskette Support  		CFG_CMD_FLASH	  flinfo, erase, protect  		CFG_CMD_FPGA	  FPGA device initialization support  		CFG_CMD_I2C	* I2C serial bus support @@ -1127,6 +1128,7 @@ The following options need to be configured:                  Define this to contain any number of null terminated                  strings (variable = value pairs) that will be part of                  the default enviroment compiled into the boot image. +                  For example, place something like this in your                  board's config file: @@ -1136,9 +1138,9 @@ The following options need to be configured:                  Warning: This method is based on knowledge about the                  internal format how the environment is stored by the -                U-Boot code. This is NOT an official, expoerted +                U-Boot code. This is NOT an official, exported                  interface! Although it is unlikely that this format -                will change soon, there is no guarantee either. +                will change soon, but there is no guarantee either.  		You better know what you are doing here.                  Note: overly (ab)use of the default environment is diff --git a/board/sc520_cdp/Makefile b/board/sc520_cdp/Makefile new file mode 100644 index 000000000..0f5039346 --- /dev/null +++ b/board/sc520_cdp/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2002 +# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= lib$(BOARD).a + +OBJS	:= sc520_cdp.o flash.o  +SOBJS	:= sc520_cdp_asm.o sc520_cdp_asm16.o + +$(LIB):	$(OBJS) $(SOBJS) +	$(AR) crv $@ $^ + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +-include .depend + +######################################################################### diff --git a/board/sc520_cdp/config.mk b/board/sc520_cdp/config.mk new file mode 100644 index 000000000..d4cd9986d --- /dev/null +++ b/board/sc520_cdp/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2002 +# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + + +TEXT_BASE = 0x387e0000 diff --git a/board/sc520_cdp/flash.c b/board/sc520_cdp/flash.c new file mode 100644 index 000000000..e43451286 --- /dev/null +++ b/board/sc520_cdp/flash.c @@ -0,0 +1,449 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +ulong myflush(void); + + +#define FLASH_BANK_SIZE 0x400000	/* 4 MB */ +#define MAIN_SECT_SIZE  0x20000		/* 128 KB */ + +flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; + + +#define CMD_READ_ARRAY		0x00F000F0 +#define CMD_UNLOCK1		0x00AA00AA +#define CMD_UNLOCK2		0x00550055 +#define CMD_ERASE_SETUP		0x00800080 +#define CMD_ERASE_CONFIRM	0x00300030 +#define CMD_PROGRAM		0x00A000A0 +#define CMD_UNLOCK_BYPASS	0x00200020 + +#define MEM_FLASH_ADDR1		(*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2))) +#define MEM_FLASH_ADDR2		(*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2))) + +#define BIT_ERASE_DONE		0x00800080 +#define BIT_RDY_MASK		0x00800080 +#define BIT_PROGRAM_ERROR	0x00200020 +#define BIT_TIMEOUT		0x80000000 /* our flag */ + +#define READY 1 +#define ERR   2 +#define TMO   4 + +/*----------------------------------------------------------------------- + */ + +ulong flash_init(void) +{ +    int i, j; +    ulong size = 0; + +    for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) +    { +	ulong flashbase = 0; +	flash_info[i].flash_id = +	  (AMD_MANUFACT & FLASH_VENDMASK) | +	  (AMD_ID_LV160B & FLASH_TYPEMASK); +	flash_info[i].size = FLASH_BANK_SIZE; +	flash_info[i].sector_count = CFG_MAX_FLASH_SECT; +	memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); +	if (i == 0) +	  flashbase = PHYS_FLASH_1; +	else +	  panic("configured to many flash banks!\n"); +	for (j = 0; j < flash_info[i].sector_count; j++) +	{ + +	    if (j <= 3) +	    { +		/* 1st one is 32 KB */ +		if (j == 0) +		{ +			flash_info[i].start[j] = flashbase + 0; +		} + +		/* 2nd and 3rd are both 16 KB */ +		if ((j == 1) || (j == 2)) +		{ +			flash_info[i].start[j] = flashbase + 0x8000 + (j-1)*0x4000; +		} + +		/* 4th 64 KB */ +		if (j == 3) +		{ +			flash_info[i].start[j] = flashbase + 0x10000; +		} +	    } +	    else +	    { +		flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE; +	    } +	} +	size += flash_info[i].size; +    } + +    /* +     * Protect monitor and environment sectors +     */ +    flash_protect(FLAG_PROTECT_SET, +		  i386boot_start-CFG_FLASH_BASE, +		  i386boot_end-CFG_FLASH_BASE, +		  &flash_info[0]); + +    flash_protect(FLAG_PROTECT_SET, +		  CFG_ENV_ADDR, +		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1, +		  &flash_info[0]); +    return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info  (flash_info_t *info) +{ +    int i; + +    switch (info->flash_id & FLASH_VENDMASK) +    { +    case (AMD_MANUFACT & FLASH_VENDMASK): +	printf("AMD: "); +	break; +    default: +	printf("Unknown Vendor "); +	break; +    } + +    switch (info->flash_id & FLASH_TYPEMASK) +    { +    case (AMD_ID_LV160B & FLASH_TYPEMASK): +	printf("2x Amd29F160BB (16Mbit)\n"); +	break; +    default: +	printf("Unknown Chip Type\n"); +	goto Done; +	break; +    } + +    printf("  Size: %ld MB in %d Sectors\n", +	   info->size >> 20, info->sector_count); + +    printf("  Sector Start Addresses:"); +    for (i = 0; i < info->sector_count; i++) +    { +	if ((i % 5) == 0) +	{ +	    printf ("\n   "); +	} +	printf (" %08lX%s", info->start[i], +		info->protect[i] ? " (RO)" : "     "); +    } +    printf ("\n"); + +Done: +} + +/*----------------------------------------------------------------------- + */ + +int	flash_erase (flash_info_t *info, int s_first, int s_last) +{ +    ulong result; +    int iflag, cflag, prot, sect; +    int rc = ERR_OK; +    int chip1, chip2; + +    /* first look for protection bits */ + +    if (info->flash_id == FLASH_UNKNOWN) +	return ERR_UNKNOWN_FLASH_TYPE; + +    if ((s_first < 0) || (s_first > s_last)) { +	return ERR_INVAL; +    } + +    if ((info->flash_id & FLASH_VENDMASK) != +	(AMD_MANUFACT & FLASH_VENDMASK)) { +	return ERR_UNKNOWN_FLASH_VENDOR; +    } + +    prot = 0; +    for (sect=s_first; sect<=s_last; ++sect) { +	if (info->protect[sect]) { +	    prot++; +	} +    } +    if (prot) +	return ERR_PROTECTED; + +    /* +     * Disable interrupts which might cause a timeout +     * here. Remember that our exception vectors are +     * at address 0 in the flash, and we don't want a +     * (ticker) exception to happen while the flash +     * chip is in programming mode. +     */ +    iflag = disable_interrupts(); + +    /* Start erase on unprotected sectors */ +    for (sect = s_first; sect<=s_last && !ctrlc(); sect++) +    { +	printf("Erasing sector %2d ... ", sect); + +	/* arm simple, non interrupt dependent timer */ +	reset_timer(); + +	if (info->protect[sect] == 0) +	{	/* not protected */ +	    vu_long *addr = (vu_long *)(info->start[sect]); + +	    MEM_FLASH_ADDR1 = CMD_UNLOCK1; +	    MEM_FLASH_ADDR2 = CMD_UNLOCK2; +	    MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; + +	    MEM_FLASH_ADDR1 = CMD_UNLOCK1; +	    MEM_FLASH_ADDR2 = CMD_UNLOCK2; +	    *addr = CMD_ERASE_CONFIRM; + +	    /* wait until flash is ready */ +	    chip1 = chip2 = 0; + +	    do +	    { +		result = *addr; + +		/* check timeout */ +		if (get_timer(0) > CFG_FLASH_ERASE_TOUT) +		{ +		    MEM_FLASH_ADDR1 = CMD_READ_ARRAY; +		    chip1 = TMO; +		    break; +		} + +		if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE) +			chip1 = READY; + +		if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR) +			chip1 = ERR; + +		if (!chip2 && (result >> 16) & BIT_ERASE_DONE) +			chip2 = READY; + +		if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR) +			chip2 = ERR; + +	    }  while (!chip1 || !chip2); + +	    MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + +	    if (chip1 == ERR || chip2 == ERR) +	    { +		rc = ERR_PROG_ERROR; +		goto outahere; +	    } +	    if (chip1 == TMO) +	    { +		rc = ERR_TIMOUT; +		goto outahere; +	    } + +	    printf("ok.\n"); +	} +	else /* it was protected */ +	{ +	    printf("protected!\n"); +	} +    } + +    if (ctrlc()) +      printf("User Interrupt!\n"); + +outahere: +    /* allow flash to settle - wait 10 ms */ +    udelay(10000); + +    if (iflag) +      enable_interrupts(); + + +    return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +volatile static int write_word (flash_info_t *info, ulong dest, ulong data) +{ +    vu_long *addr = (vu_long *)dest; +    ulong result; +    int rc = ERR_OK; +    int iflag; +    int chip1, chip2; + +    /* +     * Check if Flash is (sufficiently) erased +     */ +    result = *addr; +    if ((result & data) != data) +        return ERR_NOT_ERASED; + + +    /* +     * Disable interrupts which might cause a timeout +     * here. Remember that our exception vectors are +     * at address 0 in the flash, and we don't want a +     * (ticker) exception to happen while the flash +     * chip is in programming mode. +     */ +    iflag = disable_interrupts(); + +    MEM_FLASH_ADDR1 = CMD_UNLOCK1; +    MEM_FLASH_ADDR2 = CMD_UNLOCK2; +    MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS; +    *addr = CMD_PROGRAM; +    *addr = data; + +    /* arm simple, non interrupt dependent timer */ +    reset_timer(); + +    /* wait until flash is ready */ +    chip1 = chip2 = 0; +    do +    { +	result = *addr; + +	/* check timeout */ +	if (get_timer(0) > CFG_FLASH_ERASE_TOUT) +	{ +	    chip1 = ERR | TMO; +	    break; +	} +	if (!chip1 && ((result & 0x80) == (data & 0x80))) +		chip1 = READY; + +	if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) +	{ +		result = *addr; + +		if ((result & 0x80) == (data & 0x80)) +			chip1 = READY; +		else +			chip1 = ERR; +	} + +	if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16)))) +		chip2 = READY; + +	if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR)) +	{ +		result = *addr; + +		if ((result & (0x80 << 16)) == (data & (0x80 << 16))) +			chip2 = READY; +		else +			chip2 = ERR; +	} + +    }  while (!chip1 || !chip2); + +    *addr = CMD_READ_ARRAY; + +    if (chip1 == ERR || chip2 == ERR || *addr != data) +        rc = ERR_PROG_ERROR; + +    if (iflag) +      enable_interrupts(); + + +    return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +    ulong cp, wp, data; +    int l; +    int i, rc; + +    wp = (addr & ~3);	/* get lower word aligned address */ + +    /* +     * handle unaligned start bytes +     */ +    if ((l = addr - wp) != 0) { +	data = 0; +	for (i=0, cp=wp; i<l; ++i, ++cp) { +	    data = (data >> 8) | (*(uchar *)cp << 24); +	} +	for (; i<4 && cnt>0; ++i) { +	    data = (data >> 8) | (*src++ << 24); +	    --cnt; +	    ++cp; +	} +	for (; cnt==0 && i<4; ++i, ++cp) { +	    data = (data >> 8) | (*(uchar *)cp << 24); +	} + +	if ((rc = write_word(info, wp, data)) != 0) { +	    return (rc); +	} +	wp += 4; +    } + +    /* +     * handle word aligned part +     */ +    while (cnt >= 4) { +	data = *((vu_long*)src); +	if ((rc = write_word(info, wp, data)) != 0) { +	    return (rc); +	} +	src += 4; +	wp  += 4; +	cnt -= 4; +    } + +    if (cnt == 0) { +	return ERR_OK; +    } + +    /* +     * handle unaligned tail bytes +     */ +    data = 0; +    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { +	data = (data >> 8) | (*src++ << 24); +	--cnt; +    } +    for (; i<4; ++i, ++cp) { +	data = (data >> 8) | (*(uchar *)cp << 24); +    } + +    return write_word(info, wp, data); +} diff --git a/board/sc520_cdp/sc520_cdp.c b/board/sc520_cdp/sc520_cdp.c new file mode 100644 index 000000000..cc818d266 --- /dev/null +++ b/board/sc520_cdp/sc520_cdp.c @@ -0,0 +1,288 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <pci.h> +#include <asm/io.h> +#include <asm/ic/sc520.h> +#include <asm/ic/ali512x.h> + +/* ------------------------------------------------------------------------- */ + +static void irq_init(void) +{ +	 +	/* disable global interrupt mode */ +	write_mmcr_byte(SC520_PICICR, 0x40);  +	 +	/* set irq0-7 to edge */ +	write_mmcr_byte(SC520_MPICMODE, 0x00); +	 +	/* set irq9-12 to level, all the other (8, 13-15) are edge */ +	write_mmcr_byte(SC520_SL1PICMODE, 0x1e); +	 +	/* set irq16-24 (unused slave pic2) to level */ +	write_mmcr_byte(SC520_SL2PICMODE, 0xff); +	 +	/* active low polarity on PIC interrupt pins,  +	   active high polarity on all other irq pins */ +	write_mmcr_word(SC520_INTPINPOL, 0); + +	/* set irq number mapping */ +	write_mmcr_byte(SC520_GPTMR0MAP,0);            /* disable GP timer 0 INT */        +	write_mmcr_byte(SC520_GPTMR1MAP,0);            /* disable GP timer 1 INT */ +	write_mmcr_byte(SC520_GPTMR2MAP,0);            /* disable GP timer 2 INT */ +	write_mmcr_byte(SC520_PIT0MAP,0x1);            /* Set PIT timer 0 INT to IRQ0 */  +	write_mmcr_byte(SC520_PIT1MAP,0);              /* diable PIT timer 1 INT */ +	write_mmcr_byte(SC520_PIT2MAP,0);              /* diable PIT timer 2 INT */ +	write_mmcr_byte(SC520_PCIINTAMAP,0x4);         /* Set PCI INT A to IRQ9 */ +	write_mmcr_byte(SC520_PCIINTBMAP,0x5);         /* Set PCI INT B to IRQ10 */ +	write_mmcr_byte(SC520_PCIINTCMAP,0x6);         /* Set PCI INT C to IRQ11 */ +	write_mmcr_byte(SC520_PCIINTDMAP,0x7);         /* Set PCI INT D to IRQ12 */ +	write_mmcr_byte(SC520_DMABCINTMAP,0);          /* disable DMA INT */  +	write_mmcr_byte(SC520_SSIMAP,0);               /* disable Synchronius serial INT */ +	write_mmcr_byte(SC520_WDTMAP,0);               /* disable Watchdor INT */ +	write_mmcr_byte(SC520_RTCMAP,0x3);             /* Set RTC int to 8 */ +	write_mmcr_byte(SC520_WPVMAP,0);               /* disable write protect INT */ +	write_mmcr_byte(SC520_ICEMAP,0x2);             /* Set ICE Debug Serielport INT to IRQ1 */ +	write_mmcr_byte(SC520_FERRMAP,0x8);            /* Set FP error INT to IRQ13 */ +	write_mmcr_byte(SC520_GP0IMAP,6);              /* Set GPIRQ0 (ISA IRQ2) to IRQ9 */ +	write_mmcr_byte(SC520_GP1IMAP,2);              /* Set GPIRQ1 (SIO IRQ1) to IRQ1 */ +	write_mmcr_byte(SC520_GP2IMAP,7);              /* Set GPIRQ2 (ISA IRQ12) to IRQ12 */ +	 +	if (CFG_USE_SIO_UART) { +		write_mmcr_byte(SC520_UART1MAP,0);     /* disable internal UART1 INT */ +		write_mmcr_byte(SC520_UART2MAP,0);     /* disable internal UART2 INT */ +		write_mmcr_byte(SC520_GP3IMAP,11);     /* Set GPIRQ3 (ISA IRQ3) to IRQ3 */  +		write_mmcr_byte(SC520_GP4IMAP,12);     /* Set GPIRQ4 (ISA IRQ4) to IRQ4 */ +	} else { +		write_mmcr_byte(SC520_UART1MAP,12);    /* Set internal UART2 INT to IRQ4 */ +		write_mmcr_byte(SC520_UART2MAP,11);    /* Set internal UART2 INT to IRQ3 */ +		write_mmcr_byte(SC520_GP3IMAP,0);      /* disable GPIRQ3 (ISA IRQ3) */  +		write_mmcr_byte(SC520_GP4IMAP,0);      /* disable GPIRQ4 (ISA IRQ4) */ +	} +	 +	write_mmcr_byte(SC520_GP5IMAP,13);             /* Set GPIRQ5 (ISA IRQ5) to IRQ5 */ +	write_mmcr_byte(SC520_GP6IMAP,21);             /* Set GPIRQ6 (ISA IRQ6) to IRQ6 */ +	write_mmcr_byte(SC520_GP7IMAP,22);             /* Set GPIRQ7 (ISA IRQ7) to IRQ7 */ +	write_mmcr_byte(SC520_GP8IMAP,3);              /* Set GPIRQ8 (SIO IRQ8) to IRQ8 */ +	write_mmcr_byte(SC520_GP9IMAP,4);              /* Set GPIRQ9 (ISA IRQ9) to IRQ9 */ +	write_mmcr_byte(SC520_GP10IMAP,9);             /* Set GPIRQ10 (ISA IRQ10) to IRQ10 */           +	write_mmcr_word(SC520_PCIHOSTMAP,0x11f);       /* Map PCI hostbridge INT to NMI */ +	write_mmcr_word(SC520_ECCMAP,0x100);           /* Map SDRAM ECC failure INT to NMI */ +  +} + +/* PCI stuff */ +static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev) +{ +	char pin; +	int irq; +	 +	 +	pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); +	irq = pin-1; +	 +	switch (PCI_DEV(dev)) { +	case 20: +		break; +	case 19: +		irq+=1; +		break; +	case 18: +		irq+=2; +		break; +	case 17: +		irq+=3; +		break; +	default:  +		return; +	} +	 +	irq&=3; /* wrap around */ +	irq+=9; /* lowest IRQ is 9 */ +	 +	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, irq); +#if 0	 +	printf("fixup_irq: device %d pin %c irq %d\n",  +	       PCI_DEV(dev), 'A' + pin -1, irq); +#endif +} +  +static struct pci_controller sc520_cdp_hose = { +	fixup_irq: pci_sc520_cdp_fixup_irq, +}; + +void pci_init(void) +{ +	pci_sc520_init(&sc520_cdp_hose); +} + + +static void silence_uart(int port) +{ +	outb(0, port+1); +} + +void setup_ali_sio(int uart_primary) +{ +	ali512x_init(); +	 +	ali512x_set_fdc(ALI_ENABLED, 0x3f2, 6, 0); +	ali512x_set_pp(ALI_ENABLED, 0x278, 7, 3); +	ali512x_set_uart(ALI_ENABLED, ALI_UART1, uart_primary?0x3f8:0x3e8, 4); +	ali512x_set_uart(ALI_ENABLED, ALI_UART2, uart_primary?0x2f8:0x2e8, 3); +	ali512x_set_rtc(ALI_DISABLED, 0, 0); +	ali512x_set_kbc(ALI_ENABLED, 1, 12); +	ali512x_set_cio(ALI_ENABLED); +	 +	/* IrDa pins */ +	ali512x_cio_function(12, 1, 0, 0); +	ali512x_cio_function(13, 1, 0, 0); +	 +	/* SSI chip select pins */ +	ali512x_cio_function(14, 0, 0, 0);  /* SSI_CS */ +	ali512x_cio_function(15, 0, 0, 0);  /* SSI_MV */					      +	ali512x_cio_function(16, 0, 1, 0);  /* SSI_SPI# (inverted) */ + +	/* Board REV pins */ +	ali512x_cio_function(20, 0, 0, 1); +	ali512x_cio_function(21, 0, 0, 1); +	ali512x_cio_function(22, 0, 0, 1); +	ali512x_cio_function(23, 0, 0, 1);       +} + + +/* set up the ISA bus timing and system address mappings */ +static void bus_init(void) +{ + +	/* set up the GP IO pins */ +	write_mmcr_word(SC520_PIOPFS31_16, 0xf7ff); 	/* set the GPIO pin function 31-16 reg */		    +	write_mmcr_word(SC520_PIOPFS15_0, 0xffff);  	/* set the GPIO pin function 15-0 reg */ +	write_mmcr_byte(SC520_CSPFS, 0xf8);  		/* set the CS pin function  reg */	 +	write_mmcr_byte(SC520_CLKSEL, 0x70); + +	 +	write_mmcr_byte(SC520_GPCSRT, 1);   /* set the GP CS offset */    	 +	write_mmcr_byte(SC520_GPCSPW, 3);   /* set the GP CS pulse width */ +	write_mmcr_byte(SC520_GPCSOFF, 1);  /* set the GP CS offset */ +	write_mmcr_byte(SC520_GPRDW, 3);    /* set the RD pulse width */ +	write_mmcr_byte(SC520_GPRDOFF, 1);  /* set the GP RD offset */ +        write_mmcr_byte(SC520_GPWRW, 3);    /* set the GP WR pulse width */ +	write_mmcr_byte(SC520_GPWROFF, 1);  /* set the GP WR offset */ + +	write_mmcr_word(SC520_BOOTCSCTL, 0x1823);		/* set up timing of BOOTCS */  +	write_mmcr_word(SC520_ROMCS1CTL, 0x1823);		/* set up timing of ROMCS1 */ +	write_mmcr_word(SC520_ROMCS2CTL, 0x1823);		/* set up timing of ROMCS2 */  +	 +	/* adjust the memory map: +	 * by default the first 256MB (0x00000000 - 0x0fffffff) is mapped to SDRAM +	 * and 256MB to 1G-128k  (0x1000000 - 0x37ffffff) is mapped to PCI mmio +	 * we need to map 1G-128k - 1G (0x38000000 - 0x3fffffff) to CS1 */  +	 +		 +	/* SRAM = GPCS3 128k @ d0000-effff*/ +	write_mmcr_long(SC520_PAR2,  0x4e00400d);		 +	 +	/* IDE0 = GPCS6 1f0-1f7 */ +	write_mmcr_long(SC520_PAR3,  0x380801f0);		 + +	/* IDE1 = GPCS7 3f6 */ +	write_mmcr_long(SC520_PAR4,  0x3c0003f6);		 +	/* bootcs */ +	write_mmcr_long(SC520_PAR12, 0x8bffe800);		 +	/* romcs2 */ +	write_mmcr_long(SC520_PAR13, 0xcbfff000);		 +	/* romcs1 */ +	write_mmcr_long(SC520_PAR14, 0xabfff800);		 +	/* 680 LEDS */ +	write_mmcr_long(SC520_PAR15, 0x30000640);		 +	 +	asm ("wbinvd\n"); /* Flush cache, req. after setting the unchached attribute ona PAR */	 + +	if (CFG_USE_SIO_UART) { +		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) | UART2_DIS|UART1_DIS);	 +		setup_ali_sio(1); +	} else { +		write_mmcr_byte(SC520_ADDDECCTL, read_mmcr_byte(SC520_ADDDECCTL) & ~(UART2_DIS|UART1_DIS));	 +		setup_ali_sio(0); +		silence_uart(0x3e8); +		silence_uart(0x2e8); +	} + +} + + + +/* + * Miscelaneous platform dependent initialisations + */ + +int board_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	 +	init_sc520();	 +	bus_init(); +	irq_init(); +		 +	/* max drive current on SDRAM */ +	write_mmcr_word(SC520_DSCTL, 0x0100); +		 +	/* enter debug mode after next reset (only if jumper is also set) */ +	write_mmcr_byte(SC520_RESCFG, 0x08); +	 +	/* configure the software timer to 33.333MHz */ +	write_mmcr_byte(SC520_SWTMRCFG, 0); +	gd->bus_clk = 33333000; +	 +	return 0; +} + +int dram_init(void) +{ +	init_sc520_dram(); +	return 0; +} + +void show_boot_progress(int val) +{ +	outb(val&0xff, 0x80); +	outb((val&0xff00)>>8, 0x680); +} + + +int last_stage_init(void) +{ +	int minor; +	int major; +	 +	major = minor = 0; +	major |= ali512x_cio_in(23)?2:0; +	major |= ali512x_cio_in(22)?1:0; +	minor |= ali512x_cio_in(21)?2:0; +	minor |= ali512x_cio_in(20)?1:0; +	 +	printf("AMD SC520 CDP revision %d.%d\n", major, minor); +} diff --git a/board/sc520_cdp/sc520_cdp_asm.S b/board/sc520_cdp/sc520_cdp_asm.S new file mode 100644 index 000000000..1e255fab2 --- /dev/null +++ b/board/sc520_cdp/sc520_cdp_asm.S @@ -0,0 +1,86 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* now setup the General purpose bus to give us access to the LEDs. + * We can then use the leds to display status information. + */  + +sc520_cdp_registers: +/* size    offset        value */ +.word 1 ; .word 0x040 ; .long 0x00       /* SDRAM buffer control */ +.word 2 ; .word 0xc08 ; .long 0x0001     /* GP CS offset */ +.word 2 ; .word 0xc09 ; .long 0x0003     /* GP CS width */ +.word 2 ; .word 0xc0a ; .long 0x0001     /* GP CS width */ +.word 2 ; .word 0xc0b ; .long 0x0003     /* GP RD pulse width */ +.word 2 ; .word 0xc0c ; .long 0x0001     /* GP RD offse */ +.word 2 ; .word 0xc0d ; .long 0x0003     /* GP WR pulse width */ +.word 2 ; .word 0xc0e ; .long 0x0001     /* GP WR offset */ +.word 2 ; .word 0xc2c ; .long 0x0000     /* GPIO directionreg */ +.word 2 ; .word 0xc2a ; .long 0x0000     /* GPIO directionreg */ +.word 2 ; .word 0xc22 ; .long 0xffff     /* GPIO pin function 31-16 reg */ +.word 2 ; .word 0xc20 ; .long 0xffff     /* GPIO pin function 15-0 reg */ +.word 2 ; .word 0x0c4 ; .long 0x28000680 /* PAR 15 for access to led 680 */ +.word 0 ; .word 0x000 ; .long 0x00 + +/* board early intialization */ +.globl early_board_init +early_board_init: +        movl    $sc520_cdp_registers,%esi +init_loop:	 +        movl    $0xfffef000,%edi     /* MMCR base to edi */					 +	movw	(%esi), %bx          /* load sizer to bx */ +	cmpw	$0, %bx              /* if sie is 0 we're done */ +	je	done  +	xorl	%edx,%edx +	movw	2(%esi), %dx        /* load MMCR offset to dx */ +	addl	%edx, %edi          /* add offset to base in edi */ +	movl	4(%esi), %eax       /* load value in eax */ +	cmpw	$1, %bx +	je	byte                 /* byte op? */ +	cmpw	$2, %bx +	je	word                 /* word op? */ +	movl	%eax, (%edi)         /* must be long, then */ +	jmp	next +byte:   movb    %al,(%edi)         +	jmp	next +word:	movw	%ax,(%edi) +next:	addl	$8, %esi             /* advance esi */ +	jmp	init_loop + +	/* the leds ad 0x80 and 0x680 should now work */ +done:   movb	$0x88, %al +	out	%al, $0x80 +	movw	$0x680, %dx +	out	%al, %dx + +	jmp 	*%ebp		     /* return to caller */ + + +.globl __show_boot_progress +__show_boot_progress: +	out	%al, $0x80 +	xchg	%al, %ah +	movw	$0x680, %dx +	out	%al, %dx +	jmp	*%ebp +	 diff --git a/board/sc520_cdp/sc520_cdp_asm16.S b/board/sc520_cdp/sc520_cdp_asm16.S new file mode 100644 index 000000000..a3cadcfa5 --- /dev/null +++ b/board/sc520_cdp/sc520_cdp_asm16.S @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * 16bit initialization code. + * This code have to map the area of the boot flash + * that is used by U-boot to its final destination. + */ + +.text +.section .start16, "ax" +.code16 +.globl board_init16 +board_init16: +	/* Alias MMCR to 0xdf000 */ +	movw	$0xfffc, %dx +	movl	$0x800df0cb, %eax	 +	outl	%eax, %dx		 +	 +	/* Set ds to point to MMCR alias */ +	movw	$0xdf00, %ax		 +	movw	%ax, %ds		  +		 +	/* Map the entire flash at 0x38000000   +	 * (with BOOTCS and PAR14, use 0xabfff800 for ROMCS1) */ +	movl    $0xc0, %edi +        movl	$0x8bfff800, %eax +        movl	%eax, (%di)		 + +	/* Disable SDRAM write buffer */ +	movw    $0x40,%di +        xorw    %ax,%ax +        movb    %al, (%di)               + +	/* Disabe MMCR alias */ +	movw	$0xfffc, %dx +	movl	$0x000000cb, %eax	 +	outl	%eax, %dx		 +	 +	/* the return address is tored in bp */ +	jmp	*%bp +	 diff --git a/board/sc520_cdp/u-boot.lds b/board/sc520_cdp/u-boot.lds new file mode 100644 index 000000000..ac8d3dbec --- /dev/null +++ b/board/sc520_cdp/u-boot.lds @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +SECTIONS +{	 +	. = 0x387e0000;                     /* Where bootcode in the flash is mapped */ +	.text  : { *(.text); } +	 +        . = ALIGN(4); +        .rodata : { *(.rodata) } + +        . = 0x400000; 	                    /* Ram data segment to use */ +	_i386boot_romdata_dest = ABSOLUTE(.); +        .data : AT ( LOADADDR(.rodata) + SIZEOF(.rodata) ) { *(.data) } +	_i386boot_romdata_start = LOADADDR(.data); 	 + +        . = ALIGN(4); +        .got : AT ( LOADADDR(.data) + SIZEOF(.data) ) { *(.got) } +	_i386boot_romdata_size = SIZEOF(.data) + SIZEOF(.got); 	 + + +        . = ALIGN(4); +	_i386boot_bss_start = ABSOLUTE(.); +        .bss : { *(.bss) }	 +	_i386boot_bss_size = SIZEOF(.bss); +	 +	 +	/* 16bit realmode trampoline code */ +	.realmode 0x7c0 : AT ( LOADADDR(.got) + SIZEOF(.got) ) { *(.realmode) } +     +	_i386boot_realmode = LOADADDR(.realmode); +	_i386boot_realmode_size = SIZEOF(.realmode); +	 +	/* 16bit BIOS emulation code (just enough to boot Linux) */ +	.bios 0 : AT ( LOADADDR(.realmode) + SIZEOF(.realmode) ) { *(.bios) } +     +	_i386boot_bios = LOADADDR(.bios); +	_i386boot_bios_size = SIZEOF(.bios); +	 + +	/* The load addresses below assumes that the flash +	 * will be mapped so that 0x387f0000 == 0xffff0000 +	 * at reset time +	 * +	 * The fe00 and ff00 offsets of the start32 and start16  +	 * segments are arbitrary, the just have to be mapped +	 * at reset and the code have to fit. +	 * The fff0 offset of reset is important, however. +	 */ +	  +	  +	. = 0xfffffe00; +	.start32 : AT (0x387ffe00) { *(.start32); }  +	 +	. = 0xff00; +	.start16 : AT (0x387fff00) { *(.start16); }   +	 +	. = 0xfff0; +	.reset : AT (0x387ffff0) { *(.reset); }   +	_i386boot_end = (LOADADDR(.reset) + SIZEOF(.reset) ); +} diff --git a/common/Makefile b/common/Makefile index 3f4ff0190..67387ef64 100644 --- a/common/Makefile +++ b/common/Makefile @@ -31,7 +31,7 @@ COBJS	= main.o altera.o bedbug.o \  	  cmd_autoscript.o cmd_bedbug.o cmd_boot.o \  	  cmd_bootm.o cmd_cache.o cmd_console.o cmd_date.o \  	  cmd_dcr.o cmd_diag.o cmd_doc.o cmd_dtt.o \ -	  cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_flash.o \ +	  cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_fdos.o cmd_flash.o \  	  cmd_fpga.o cmd_i2c.o cmd_ide.o cmd_immap.o \  	  cmd_jffs2.o cmd_log.o cmd_mem.o cmd_mii.o cmd_misc.o \  	  cmd_net.o cmd_nvedit.o env_common.o \ diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 70ca999c0..a0587d019 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -70,6 +70,10 @@ static int image_info (unsigned long addr);  #endif  static void print_type (image_header_t *hdr); +#ifdef __I386__ +image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); +#endif +  /*   *  Continue booting an OS image; caller already has:   *  - copied image header to global variable `header' @@ -84,7 +88,7 @@ typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag,  			  ulong	*len_ptr,	/* multi-file image length table */  			  int	verify);	/* getenv("verify")[0] != 'n' */ -#ifndef CONFIG_ARM +#ifdef CONFIG_PPC  static boot_os_Fcn do_bootm_linux;  #else  extern boot_os_Fcn do_bootm_linux; @@ -128,9 +132,21 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	memmove (&header, (char *)addr, sizeof(image_header_t));  	if (ntohl(hdr->ih_magic) != IH_MAGIC) { +#ifdef __I386__	/* correct image format not implemented yet - fake it */ +		if (fake_header(hdr, (void*)addr, -1) != NULL) { +			/* to compensate for the addition below */ +			addr -= sizeof(image_header_t); +			/* turnof verify, +			 * fake_header() does not fake the data crc +			 */ +			verify = 0; +		} else +#endif	/* __I386__ */ +	    {  		printf ("Bad Magic Number\n");  		SHOW_BOOT_PROGRESS (-1);  		return 1; +	    }  	}  	SHOW_BOOT_PROGRESS (2); @@ -148,7 +164,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	SHOW_BOOT_PROGRESS (3);  	/* for multi-file images we need the data part, too */ -	print_image_hdr ((image_header_t *)addr); +	print_image_hdr (hdr);  	data = addr + sizeof(image_header_t);  	len  = ntohl(hdr->ih_size); @@ -166,8 +182,17 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	len_ptr = (ulong *)data; -	if (hdr->ih_arch != IH_CPU_PPC && hdr->ih_arch != IH_CPU_ARM) { -		printf ("Unsupported Architecture\n"); +#if defined(__PPC__) +	if (hdr->ih_arch != IH_CPU_PPC) +#elif defined(__ARM__) +	if (hdr->ih_arch != IH_CPU_ARM) +#elif defined(__I386__) +	if (hdr->ih_arch != IH_CPU_I386) +#else +# error Unknown CPU type +#endif +	{ +		printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch);  		SHOW_BOOT_PROGRESS (-4);  		return 1;  	} @@ -201,7 +226,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	switch (hdr->ih_comp) {  	case IH_COMP_NONE: -		if(hdr->ih_load == addr) { +		if(ntohl(hdr->ih_load) == addr) {  			printf ("   XIP %s ... ", name);  		} else {  #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) @@ -294,7 +319,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	return 1;  } -#ifndef CONFIG_ARM +#ifdef CONFIG_PPC  static void  do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  		int	argc, char *argv[], diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 8e6b7350c..e45b3361c 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -51,7 +51,7 @@  #include <rtc.h>  #endif -#if (CONFIG_COMMANDS & CFG_CMD_FDC) +#if ((CONFIG_COMMANDS & CFG_CMD_FDC) || (CONFIG_COMMANDS & CFG_CMD_FDOS))  typedef struct { @@ -192,7 +192,10 @@ static FDC_COMMAND_STRUCT cmd; /* global command struct */  /* reads a Register of the FDC */  unsigned char read_fdc_reg(unsigned int addr)  { -	volatile unsigned char *val = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS + (addr * CFG_ISA_IO_STRIDE) + CFG_ISA_IO_OFFSET); +	volatile unsigned char *val = +		(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS + +					   (addr * CFG_ISA_IO_STRIDE) + +					   CFG_ISA_IO_OFFSET);  	return val [0];  } @@ -200,7 +203,10 @@ unsigned char read_fdc_reg(unsigned int addr)  /* writes a Register of the FDC */  void write_fdc_reg(unsigned int addr, unsigned char val)  { -        volatile unsigned char *tmp = (volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS + (addr * CFG_ISA_IO_STRIDE) + CFG_ISA_IO_OFFSET); +        volatile unsigned char *tmp = +		(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS + +					   (addr * CFG_ISA_IO_STRIDE) + +					   CFG_ISA_IO_OFFSET);  	tmp[0]=val;  } @@ -279,7 +285,8 @@ int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)  	head = sect / pFG->sect; /* head nr */  	sect =  sect % pFG->sect; /* remaining blocks */  	sect++; /* sectors are 1 based */ -	PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr); +	PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n", +		pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr);  	if(head|=0) { /* max heads = 2 */  		pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */ @@ -588,7 +595,7 @@ int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  * setup the fdc according the datasheet  * assuming in PS2 Mode  */ -int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG) +int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  {  	int i; @@ -601,7 +608,7 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)  	for(i=0; i<255; i++) /* then we wait some time */  		udelay(500);  	/* then, we clear the reset in the DOR */ -	pCMD->drive=CFG_FDC_DRIVE_NUMBER; +	pCMD->drive=drive;  	select_fdc_drive(pCMD);  	/* initialize the CCR */  	write_fdc_reg(FDC_CCR,pFG->rate); @@ -621,9 +628,8 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)  			PRINTF("Sense Interrupt for drive %d failed\n",i);  		}  	} -	/* assuming drive 0 for rest of configuration -	 * issue the configure command */ -	pCMD->drive=CFG_FDC_DRIVE_NUMBER; +	/* issue the configure command */ +	pCMD->drive=drive;  	select_fdc_drive(pCMD);  	pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;  	if(fdc_issue_cmd(pCMD,pFG)==FALSE) { @@ -644,7 +650,74 @@ int fdc_setup(FDC_COMMAND_STRUCT *pCMD,	FD_GEO_STRUCT *pFG)  	/*	write_fdc_reg(FDC_DOR,0x04); */  	return TRUE;  } +#endif /* ((CONFIG_COMMANDS & CFG_CMD_FDC)||(CONFIG_COMMANDS & CFG_CMD_FDOS))*/ + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +/* Low level functions for the Floppy-DOS layer                              */ +/************************************************************************** +* int fdc_fdos_init +* initialize the FDC layer  +*  +*/ +int fdc_fdos_init (int drive) +{ +	FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type; +	FDC_COMMAND_STRUCT *pCMD = &cmd; +     +	/* setup FDC and scan for drives  */ +	if(fdc_setup(drive,pCMD,pFG)==FALSE) { +		printf("\n** Error in setup FDC **\n"); +		return FALSE; +	} +	if(fdc_check_drive(pCMD,pFG)==FALSE) { +		printf("\n** Error in check_drives **\n"); +		return FALSE; +	} +	if((pCMD->flags&(1<<drive))==0) { +		/* drive not available */ +		printf("\n** Drive %d not available **\n",drive); +		return FALSE; +	} +	if((pCMD->flags&(0x10<<drive))==0) { +		/* no disk inserted */ +		printf("\n** No disk inserted in drive %d **\n",drive); +		return FALSE; +	} +	/* ok, we have a valid source */ +	pCMD->drive=drive; + +	/* read first block */ +	pCMD->blnr=0; +        return TRUE; +} +/************************************************************************** +* int fdc_fdos_seek +* parameter is a block number  +*/ +int fdc_fdos_seek (int where) +{ +	FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type; +	FDC_COMMAND_STRUCT *pCMD = &cmd; + +        pCMD -> blnr = where ; +        return (fdc_seek (pCMD, pFG)); +} +/************************************************************************** +* int fdc_fdos_read +*  the length is in block number +*/ +int fdc_fdos_read (void *buffer, int len) +{ +	FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type; +	FDC_COMMAND_STRUCT *pCMD = &cmd; + +        return (fdc_read_data (buffer, len, pCMD, pFG)); +} +#endif  /* (CONFIG_COMMANDS & CFG_CMD_FDOS)                                  */ + +#if (CONFIG_COMMANDS & CFG_CMD_FDC)  /****************************************************************************   * main routine do_fdcboot   */ @@ -677,7 +750,7 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		return 1;  	}  	/* setup FDC and scan for drives  */ -	if(fdc_setup(pCMD,pFG)==FALSE) { +	if(fdc_setup(boot_drive,pCMD,pFG)==FALSE) {  		printf("\n** Error in setup FDC **\n");  		return 1;  	} diff --git a/common/cmd_fdos.c b/common/cmd_fdos.c new file mode 100644 index 000000000..763f4181a --- /dev/null +++ b/common/cmd_fdos.c @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Dos floppy support + */ + +#include <common.h> +#include <config.h> +#include <command.h> +#include <fdc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +/*----------------------------------------------------------------------------- + * do_fdosboot --  + *----------------------------------------------------------------------------- + */ +int do_fdosboot(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +    char *name; +    char *ep; +    int size; +    int rcode = 0; +    char buf [10]; +    int drive = CFG_FDC_DRIVE_NUMBER; +     +    /* pre-set load_addr */ +    if ((ep = getenv("loadaddr")) != NULL) { +        load_addr = simple_strtoul(ep, NULL, 16); +    } + +    /* pre-set Boot file name */ +    if ((name = getenv("bootfile")) == NULL) { +        name = "pImage"; +    } + +    switch (argc) { +    case 1: +        break; +    case 2: +	/* only one arg - accept two forms: +         * just load address, or just boot file name. +         * The latter form must be written "filename" here. +         */         +        if (argv[1][0] == '"') {	/* just boot filename */ +            name = argv [1]; +        } else {			/* load address	*/ +            load_addr = simple_strtoul(argv[1], NULL, 16); +        } +        break; +    case 3: +        load_addr = simple_strtoul(argv[1], NULL, 16); +        name = argv [2]; +        break; +    default: +        printf ("Usage:\n%s\n", cmdtp->usage); +        break; +    } + +    /* Init physical layer                                                   */ +    if (!fdc_fdos_init (drive)) { +        return (-1); +    } +     +    /* Open file                                                             */ +    if (dos_open (name) < 0) { +        printf ("Unable to open %s\n", name); +        return 1; +    } +    if ((size = dos_read (load_addr)) < 0) { +        printf ("boot error\n"); +        return 1; +    } +    flush_cache (load_addr, size); + +    sprintf(buf, "%x", size); +    setenv("filesize", buf); + +    printf("Floppy DOS load complete: %d bytes loaded to 0x%lx\n", +           size, load_addr); +     +    /* Check if we should attempt an auto-start */ +    if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { +        char *local_args[2]; +        extern int do_bootm (cmd_tbl_t *, int, int, char *[]); +        local_args[0] = argv[0]; +        local_args[1] = NULL; +        printf ("Automatic boot of image at addr 0x%08lX ...\n", load_addr); +        rcode = do_bootm (cmdtp, 0, 1, local_args); +    } +    return rcode; +} + +/*----------------------------------------------------------------------------- + * do_fdosls --  + *----------------------------------------------------------------------------- + */ +int do_fdosls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +    char *path = ""; +    int drive = CFG_FDC_DRIVE_NUMBER; +     +    switch (argc) { +    case 1: +        break; +    case 2: +        path = argv [1]; +        break; +    } + +    /* Init physical layer                                                   */ +    if (!fdc_fdos_init (drive)) { +        return (-1); +    } +    /* Open directory                                                        */ +    if (dos_open (path) < 0) { +        printf ("Unable to open %s\n", path); +        return 1; +    } +    return (dos_dir ()); +} + +#endif diff --git a/common/cmd_ide.c b/common/cmd_ide.c index 9cbfe1bb0..e514cf71e 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -44,6 +44,9 @@  #ifdef CONFIG_STATUS_LED  # include <status_led.h>  #endif +#ifdef __I386__ +#include <asm/io.h> +#endif  #ifdef CONFIG_SHOW_BOOT_PROGRESS  # include <status_led.h> @@ -114,7 +117,9 @@ ulong ide_bus_offset[CFG_IDE_MAXBUS] = {  #endif  }; +#ifdef __PPC__  #define	ATA_CURR_BASE(dev)	(CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)]) +#endif  static int	    ide_bus_ok[CFG_IDE_MAXBUS]; @@ -142,9 +147,11 @@ static uchar ide_wait  (int dev, ulong t);  #define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ -static void __inline__ outb(int dev, int port, unsigned char val); -static unsigned char __inline__ inb(int dev, int port); +static void __inline__ ide_outb(int dev, int port, unsigned char val); +static unsigned char __inline__ ide_inb(int dev, int port); +#ifdef __PPC__  static void input_swap_data(int dev, ulong *sect_buf, int words); +#endif  static void input_data(int dev, ulong *sect_buf, int words);  static void output_data(int dev, ulong *sect_buf, int words);  static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); @@ -517,14 +524,14 @@ void ide_init (void)  		/* Select device  		 */  		udelay (100000);		/* 100 ms */ -		outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); +		ide_outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));  		udelay (100000);		/* 100 ms */  		i = 0;  		do {  			udelay (10000);		/* 10 ms */ -			c = inb (dev, ATA_STATUS); +			c = ide_inb (dev, ATA_STATUS);  			i++;  			if (i > (ATA_RESET_TIME * 100)) {  				puts ("** Timeout **\n"); @@ -679,30 +686,48 @@ set_pcmcia_timing (int pmode)  /* ------------------------------------------------------------------------- */ +#ifdef __PPC__  static void __inline__ -outb(int dev, int port, unsigned char val) +ide_outb(int dev, int port, unsigned char val)  {  	/* Ensure I/O operations complete */  	__asm__ volatile("eieio");  	*((uchar *)(ATA_CURR_BASE(dev)+port)) = val;  #if 0 -	printf ("OUTB: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val); +	printf ("ide_outb: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val);  #endif  } +#else	/* ! __PPC__ */ +static void __inline__ +ide_outb(int dev, int port, unsigned char val) +{ +	outb(val, port); +} +#endif	/* __PPC__ */ + +#ifdef __PPC__  static unsigned char __inline__ -inb(int dev, int port) +ide_inb(int dev, int port)  {  	uchar val;  	/* Ensure I/O operations complete */  	__asm__ volatile("eieio");  	val = *((uchar *)(ATA_CURR_BASE(dev)+port));  #if 0 -	printf ("INB: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val); +	printf ("ide_inb: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val);  #endif  	return (val);  } +#else	/* ! __PPC__ */ +static unsigned char __inline__ +ide_inb(int dev, int port) +{ +	return inb(port); +} +#endif	/* __PPC__ */ +#ifdef __PPC__  __inline__ unsigned ld_le16(const volatile unsigned short *addr)  {  	unsigned val; @@ -722,7 +747,14 @@ input_swap_data(int dev, ulong *sect_buf, int words)  		*dbuf++ = ld_le16(pbuf);  	}  } +#else	/* ! __PPC__ */ +#define input_swap_data(x,y,z) input_data(x,y,z) +#endif	/* __PPC__ */ + + + +#ifdef __PPC__  static void  output_data(int dev, ulong *sect_buf, int words)  { @@ -738,7 +770,15 @@ output_data(int dev, ulong *sect_buf, int words)  		*pbuf = *dbuf++;  	}  } +#else	/* ! __PPC__ */ +static void +output_data(int dev, ulong *sect_buf, int words) +{ +	outsw(ATA_DATA_REG, sect_buf, words<<1); +} +#endif	/* __PPC__ */ +#ifdef __PPC__  static void  input_data(int dev, ulong *sect_buf, int words)  { @@ -754,6 +794,14 @@ input_data(int dev, ulong *sect_buf, int words)  		*dbuf++ = *pbuf;  	}  } +#else	/* ! __PPC__ */ +static void +input_data(int dev, ulong *sect_buf, int words) +{ +	insw(ATA_DATA_REG, sect_buf, words << 1); +} + +#endif	/* __PPC__ */  /* -------------------------------------------------------------------------   */ @@ -773,19 +821,19 @@ static void ide_ident (block_dev_desc_t *dev_desc)  	ide_led (DEVICE_LED(device), 1);	/* LED on	*/  	/* Select device  	 */ -	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); +	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));  	dev_desc->if_type=IF_TYPE_IDE;  #ifdef CONFIG_ATAPI  	/* check signature */ -	if ((inb(device,ATA_SECT_CNT)==0x01) && -		 (inb(device,ATA_SECT_NUM)==0x01) && -		 (inb(device,ATA_CYL_LOW)==0x14) && -		 (inb(device,ATA_CYL_HIGH)==0xEB)) { +	if ((ide_inb(device,ATA_SECT_CNT) == 0x01) && +		 (ide_inb(device,ATA_SECT_NUM) == 0x01) && +		 (ide_inb(device,ATA_CYL_LOW)  == 0x14) && +		 (ide_inb(device,ATA_CYL_HIGH) == 0xEB)) {  		/* ATAPI Signature found */  		dev_desc->if_type=IF_TYPE_ATAPI;  		/* Start Ident Command  		 */ -		outb (device, ATA_COMMAND, ATAPI_CMD_IDENT); +		ide_outb (device, ATA_COMMAND, ATAPI_CMD_IDENT);  		/*  		 * Wait for completion - ATAPI devices need more time  		 * to become ready @@ -797,7 +845,7 @@ static void ide_ident (block_dev_desc_t *dev_desc)  	{  		/* Start Ident Command  		 */ -		outb (device, ATA_COMMAND, ATA_CMD_IDENT); +		ide_outb (device, ATA_COMMAND, ATA_CMD_IDENT);  		/* Wait for completion  		 */ @@ -867,15 +915,15 @@ static void ide_ident (block_dev_desc_t *dev_desc)  #if 0 	/* only used to test the powersaving mode,  	 * if enabled, the drive goes after 5 sec  	 * in standby mode */ -	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); +	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));  	c = ide_wait (device, IDE_TIME_OUT); -	outb (device, ATA_SECT_CNT, 1); -	outb (device, ATA_LBA_LOW,  0); -	outb (device, ATA_LBA_MID,  0); -	outb (device, ATA_LBA_HIGH, 0); -	outb (device, ATA_DEV_HD,   ATA_LBA		| +	ide_outb (device, ATA_SECT_CNT, 1); +	ide_outb (device, ATA_LBA_LOW,  0); +	ide_outb (device, ATA_LBA_MID,  0); +	ide_outb (device, ATA_LBA_HIGH, 0); +	ide_outb (device, ATA_DEV_HD,   ATA_LBA		|  				    ATA_DEVICE(device)); -	outb (device, ATA_COMMAND,  0xe3); +	ide_outb (device, ATA_COMMAND,  0xe3);  	udelay (50);  	c = ide_wait (device, IDE_TIME_OUT);	/* can't take over 500 ms */  #endif @@ -897,7 +945,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)  	/* Select device  	 */ -	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); +	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));  	c = ide_wait (device, IDE_TIME_OUT);  	if (c & ATA_STAT_BUSY) { @@ -907,7 +955,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)  	/* first check if the drive is in Powersaving mode, if yes,  	 * increase the timeout value */ -	outb (device, ATA_COMMAND,  ATA_CMD_CHK_PWR); +	ide_outb (device, ATA_COMMAND,  ATA_CMD_CHK_PWR);  	udelay (50);  	c = ide_wait (device, IDE_TIME_OUT);	/* can't take over 500 ms */ @@ -919,7 +967,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)  	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {  		printf ("No Powersaving mode %X\n", c);  	} else { -		c = inb(device,ATA_SECT_CNT); +		c = ide_inb(device,ATA_SECT_CNT);  		PRINTF("Powersaving %02X\n",c);  		if(c==0)  			pwrsave=1; @@ -935,14 +983,14 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)  			break;  		} -		outb (device, ATA_SECT_CNT, 1); -		outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF); -		outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF); -		outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); -		outb (device, ATA_DEV_HD,   ATA_LBA		| +		ide_outb (device, ATA_SECT_CNT, 1); +		ide_outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF); +		ide_outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF); +		ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); +		ide_outb (device, ATA_DEV_HD,   ATA_LBA		|  					    ATA_DEVICE(device)	|  					    ((blknr >> 24) & 0xF) ); -		outb (device, ATA_COMMAND,  ATA_CMD_READ); +		ide_outb (device, ATA_COMMAND,  ATA_CMD_READ);  		udelay (50); @@ -960,7 +1008,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)  		}  		input_data (device, buffer, ATA_SECTORWORDS); -		(void) inb (device, ATA_STATUS);	/* clear IRQ */ +		(void) ide_inb (device, ATA_STATUS);	/* clear IRQ */  		++n;  		++blknr; @@ -983,7 +1031,7 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)  	/* Select device  	 */ -	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); +	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));  	while (blkcnt-- > 0) { @@ -994,14 +1042,14 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)  			goto WR_OUT;  		} -		outb (device, ATA_SECT_CNT, 1); -		outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF); -		outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF); -		outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); -		outb (device, ATA_DEV_HD,   ATA_LBA		| +		ide_outb (device, ATA_SECT_CNT, 1); +		ide_outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF); +		ide_outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF); +		ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); +		ide_outb (device, ATA_DEV_HD,   ATA_LBA		|  					    ATA_DEVICE(device)	|  					    ((blknr >> 24) & 0xF) ); -		outb (device, ATA_COMMAND,  ATA_CMD_WRITE); +		ide_outb (device, ATA_COMMAND,  ATA_CMD_WRITE);  		udelay (50); @@ -1014,7 +1062,7 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)  		}  		output_data (device, buffer, ATA_SECTORWORDS); -		c = inb (device, ATA_STATUS);	/* clear IRQ */ +		c = ide_inb (device, ATA_STATUS);	/* clear IRQ */  		++n;  		++blknr;  		buffer += ATA_SECTORWORDS; @@ -1063,7 +1111,7 @@ static uchar ide_wait (int dev, ulong t)  	ulong delay = 10 * t;		/* poll every 100 us */  	uchar c; -	while ((c = inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { +	while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {  		udelay (100);  		if (delay-- == 0) {  			break; @@ -1188,6 +1236,7 @@ static void ide_led (uchar led, uchar status)  #define AT_PRINTF(fmt,args...)  #endif +#ifdef __PPC__  /* since ATAPI may use commands with not 4 bytes alligned length   * we have our own transfer functions, 2 bytes alligned */  static void @@ -1218,6 +1267,22 @@ input_data_shorts(int dev, ushort *sect_buf, int shorts)  	}  } +#else	/* ! __PPC__ */ +static void +output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ +	outsw(ATA_DATA_REG, sect_buf, shorts); +} + + +static void +input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ +	insw(ATA_DATA_REG, sect_buf, shorts); +} + +#endif	/* __PPC__ */ +  /*   * Wait until (Status & mask) == res, or timeout (in ms)   * Return last status @@ -1229,9 +1294,8 @@ static uchar atapi_wait_mask (int dev, ulong t,uchar mask, uchar res)  	ulong delay = 10 * t;		/* poll every 100 us */  	uchar c; -	c = inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */ -	while (((c = inb(dev, ATA_STATUS)) & mask) -			!= res) { +	c = ide_inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */ +	while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {  		/* break if error occurs (doesn't make sense to wait more) */  		if((c & ATA_STAT_ERR)==ATA_STAT_ERR)  			break; @@ -1256,7 +1320,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha  	 */  	mask = ATA_STAT_BUSY|ATA_STAT_DRQ;  	res = 0; -	outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); +	ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));  	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);  	if ((c & mask) != res) {  		printf ("ATAPI_ISSUE: device %d not ready status %X\n", device,c); @@ -1264,12 +1328,12 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha  		goto AI_OUT;  	}  	/* write taskfile */ -	outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ -	outb (device, ATA_CYL_LOW,  (unsigned char)(buflen & 0xFF)); -	outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF)); -	outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device)); +	ide_outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ +	ide_outb (device, ATA_CYL_LOW,  (unsigned char)(buflen & 0xFF)); +	ide_outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF)); +	ide_outb (device, ATA_DEV_HD,   ATA_LBA | ATA_DEVICE(device)); -	outb (device, ATA_COMMAND,  ATAPI_CMD_PACKET); +	ide_outb (device, ATA_COMMAND,  ATAPI_CMD_PACKET);  	udelay (50);  	mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR; @@ -1295,7 +1359,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha  	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);  	if ((c & mask) != res ) {  		if (c & ATA_STAT_ERR) { -			err=(inb(device,ATA_ERROR_REG))>>4; +			err=(ide_inb(device,ATA_ERROR_REG))>>4;  			AT_PRINTF("atapi_issue 1 returned sense key %X status %02X\n",err,c);  		} else {  			printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x)  status 0x%02x\n", ccb[0],c); @@ -1303,9 +1367,9 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha  		}  		goto AI_OUT;  	} -	n=inb(device, ATA_CYL_HIGH); +	n=ide_inb(device, ATA_CYL_HIGH);  	n<<=8; -	n+=inb(device, ATA_CYL_LOW); +	n+=ide_inb(device, ATA_CYL_LOW);  	if(n>buflen) {  		printf("ERROR, transfer bytes %d requested only %d\n",n,buflen);  		err=0xff; @@ -1324,7 +1388,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha  		 /* we transfer shorts */  		n>>=1;  		/* ok now decide if it is an in or output */ -		if ((inb(device, ATA_SECT_CNT)&0x02)==0) { +		if ((ide_inb(device, ATA_SECT_CNT)&0x02)==0) {  			AT_PRINTF("Write to device\n");  			output_data_shorts(device,(unsigned short *)buffer,n);  		} else { @@ -1337,7 +1401,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha  	res=0;  	c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);  	if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { -		err=(inb(device,ATA_ERROR_REG) >> 4); +		err=(ide_inb(device,ATA_ERROR_REG) >> 4);  		AT_PRINTF("atapi_issue 2 returned sense key %X status %X\n",err,c);  	} else {  		err = 0; diff --git a/common/command.c b/common/command.c index f70cad8cb..cab68abf8 100644 --- a/common/command.c +++ b/common/command.c @@ -70,6 +70,7 @@  #include <cmd_vfd.h>		/* load a bitmap to the VFDs on TRAB */  #include <cmd_log.h> +#include <cmd_fdos.h>  /*   * HELP command @@ -253,6 +254,8 @@ cmd_tbl_t cmd_tbl[] = {  	CMD_TBL_FCCINFO  	CMD_TBL_FLERASE  	CMD_TBL_FDC +        CMD_TBL_FDOS_BOOT +        CMD_TBL_FDOS_LS  	CMD_TBL_FLINFO  	CMD_TBL_FPGA  	CMD_TBL_JFFS2_FSINFO diff --git a/cpu/i386/Makefile b/cpu/i386/Makefile new file mode 100644 index 000000000..1482398ef --- /dev/null +++ b/cpu/i386/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2002 +# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= lib$(CPU).a + +START	= start.o start16.o reset.o  +OBJS	= serial.o interrupts.o cpu.o timer.o +	   +all:	.depend $(START) $(LIB) + +$(LIB):	$(OBJS) +	$(AR) crv $@ $(OBJS) + +######################################################################### + +.depend:	Makefile $(START:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/i386/config.mk b/cpu/i386/config.mk new file mode 100644 index 000000000..70caeb270 --- /dev/null +++ b/cpu/i386/config.mk @@ -0,0 +1,26 @@ +# +# (C) Copyright 2002 +# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_RELFLAGS += # -pipe -mpreferred-stack-boundary=2 -fno-builtin -nostdinc -nostdlib + +PLATFORM_CPPFLAGS += -march=i386 diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c new file mode 100644 index 000000000..669823f94 --- /dev/null +++ b/cpu/i386/cpu.c @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + *  + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> + +int cpu_init(void) +{ +	return 0; +} + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	extern void reset_cpu(ulong addr); + +	printf ("resetting ...\n"); +	udelay(50000);				/* wait 50 ms */ +	disable_interrupts(); +	reset_cpu(0); + +	/*NOTREACHED*/ +	return 0; +} + +void  flush_cache (unsigned long dummy1, unsigned long dummy2) +{ +	asm("wbinvd\n"); +	return; +} + diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c new file mode 100644 index 000000000..81d688185 --- /dev/null +++ b/cpu/i386/interrupts.c @@ -0,0 +1,583 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <syscall.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/i8259.h> +#include <asm/ibmpc.h> + + +#if 0 +/* done */ +int	interrupt_init     (void); +void	irq_install_handler(int, interrupt_handler_t *, void *); +void	irq_free_handler   (int); +void	enable_interrupts  (void); +int	disable_interrupts (void); + +/* todo */ +void	timer_interrupt    (struct pt_regs *); +void	external_interrupt (struct pt_regs *); +void	reset_timer	   (void); +ulong	get_timer	   (ulong base); +void	set_timer	   (ulong t); + +#endif + +struct idt_entry { +	u16	base_low; +	u16	selector; +	u8	res; +	u8	access; +	u16	base_high; +} __attribute__ ((packed)); + + +struct idt_entry idt[256]; + + +#define MAX_IRQ 16 + +typedef struct irq_handler {  +	struct irq_handler *next; +	interrupt_handler_t* isr_func; +	void *isr_data; +} irq_handler_t; + +#define IRQ_DISABLED   1 + +typedef struct { +	irq_handler_t *handler; +	unsigned long status; +} irq_desc_t; + +static irq_desc_t irq_table[MAX_IRQ]; + + +/* syscall stuff, very untested  + * the current approach which includes copying + * part of the stack will work badly for  + * varargs functions. + * if we were to store the top three words on the + * stack (eip, ss, eflags) somwhere and add 14 to + * %esp .... + */ +asm(".globl syscall_entry\n" \ +        "syscall_entry:\n" \ +        "movl   12(%esp), %eax\n" \ +	"movl   %esp, %ebx\n" \ +        "addl   $16, %ebx\n" \ +        "pushl  %ebx\n" \ +        "pushl  %eax\n" \ +        "call   do_syscall\n" \ +        "addl   $8, %esp\n" \ +        "iret\n"); + +void __attribute__ ((regparm(0))) syscall_entry(void); + +int __attribute__ ((regparm(0))) do_syscall(u32 nr, u32 *stack) +{ +	if (nr<NR_SYSCALLS) { +		/* We copy 8 args of the syscall, +		 * this will be a problem with the  +		 * printf syscall .... */ +		int (*fp)(u32, u32, u32, u32, +			  u32, u32, u32, u32); +		fp = syscall_tbl[nr]; +		return fp(stack[0], stack[1], stack[2], stack[3], +					     stack[4], stack[5], stack[6], stack[7]); +	} +	 +	return -1; +} +	 + +asm ("irq_return:\n" +     "     addl  $4, %esp\n" +     "     popa\n" +     "     iret\n"); + +asm ("exp_return:\n" +     "     addl  $12, %esp\n" +     "     pop   %esp\n" +     "     popa\n" +     "     iret\n"); + +char exception_stack[4096]; + +#define DECLARE_INTERRUPT(x) \ +	asm(".globl irq_"#x"\n" \ +		    "irq_"#x":\n" \ +		    "pusha \n" \ +		    "pushl $"#x"\n" \ +		    "pushl $irq_return\n" \ +                    "jmp   do_irq\n"); \ +	void __attribute__ ((regparm(0))) irq_##x(void) + +#define DECLARE_EXCEPTION(x, f) \ +	asm(".globl exp_"#x"\n" \ +		    "exp_"#x":\n" \ +		    "pusha \n" \ +		    "movl     %esp, %ebx\n" \ +		    "movl     $exception_stack, %eax\n" \ +		    "movl     %eax, %esp \n" \ +		    "pushl    %ebx\n" \ +		    "movl     32(%esp), %ebx\n" \ +		    "xorl     %edx, %edx\n" \ +		    "movw     36(%esp), %dx\n" \ +		    "pushl    %edx\n" \ +		    "pushl    %ebx\n" \ +		    "pushl    $"#x"\n" \ +		    "pushl    $exp_return\n" \ +		    "jmp      "#f"\n"); \ +	void __attribute__ ((regparm(0))) exp_##x(void) + +DECLARE_EXCEPTION(0, divide_exception_entry);      /* Divide exception */ +DECLARE_EXCEPTION(1, debug_exception_entry);       /* Debug exception */ +DECLARE_EXCEPTION(2, nmi_entry);                   /* NMI */ +DECLARE_EXCEPTION(3, unknown_exception_entry);     /* Breakpoint/Coprocessor Error */ +DECLARE_EXCEPTION(4, unknown_exception_entry);     /* Overflow */ +DECLARE_EXCEPTION(5, unknown_exception_entry);     /* Bounds */ +DECLARE_EXCEPTION(6, invalid_instruction_entry);   /* Invalid instruction */ +DECLARE_EXCEPTION(7, unknown_exception_entry);     /* Device not present */ +DECLARE_EXCEPTION(8, double_fault_entry);          /* Double fault */ +DECLARE_EXCEPTION(9, unknown_exception_entry);     /* Co-processor segment overrun */ +DECLARE_EXCEPTION(10, invalid_tss_exception_entry);/* Invalid TSS */ +DECLARE_EXCEPTION(11, seg_fault_entry);            /* Segment not present */ +DECLARE_EXCEPTION(12, stack_fault_entry);          /* Stack overflow */ +DECLARE_EXCEPTION(13, gpf_entry);                  /* GPF */ +DECLARE_EXCEPTION(14, page_fault_entry);           /* PF */ +DECLARE_EXCEPTION(15, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(16, fp_exception_entry);         /* Floating point */ +DECLARE_EXCEPTION(17, alignment_check_entry);      /* alignment check */ +DECLARE_EXCEPTION(18, machine_check_entry);        /* machine check */ +DECLARE_EXCEPTION(19, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(20, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(21, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(22, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(23, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(24, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(25, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(26, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(27, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(28, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(29, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(30, unknown_exception_entry);    /* Reserved */ +DECLARE_EXCEPTION(31, unknown_exception_entry);    /* Reserved */ + +DECLARE_INTERRUPT(0); +DECLARE_INTERRUPT(1); +DECLARE_INTERRUPT(3); +DECLARE_INTERRUPT(4); +DECLARE_INTERRUPT(5); +DECLARE_INTERRUPT(6); +DECLARE_INTERRUPT(7); +DECLARE_INTERRUPT(8); +DECLARE_INTERRUPT(9); +DECLARE_INTERRUPT(10); +DECLARE_INTERRUPT(11); +DECLARE_INTERRUPT(12); +DECLARE_INTERRUPT(13); +DECLARE_INTERRUPT(14); +DECLARE_INTERRUPT(15); +   +void __attribute__ ((regparm(0))) default_isr(void);  +asm ("default_isr: iret\n"); + +void disable_irq(int irq)  +{ +	if (irq >= MAX_IRQ) { +		return; +	} +	irq_table[irq].status |= IRQ_DISABLED; +	 +} + +void enable_irq(int irq)  +{ +	if (irq >= MAX_IRQ) { +		return; +	} +	irq_table[irq].status &= ~IRQ_DISABLED; +} + +/* masks one specific IRQ in the PIC */ +static void unmask_irq(int irq) +{ +	int imr_port; +	 +	if (irq >= MAX_IRQ) { +		return; +	} +	if (irq > 7) { +		imr_port = SLAVE_PIC + IMR; +	} else { +		imr_port = MASTER_PIC + IMR; +	} +	 +	outb(inb(imr_port)&~(1<<(irq&7)), imr_port); +} + + +/* unmasks one specific IRQ in the PIC */ +static void mask_irq(int irq) +{ +	int imr_port; +	 +	if (irq >= MAX_IRQ) { +		return; +	} +	if (irq > 7) { +		imr_port = SLAVE_PIC + IMR; +	} else { +		imr_port = MASTER_PIC + IMR; +	} +	 +	outb(inb(imr_port)|(1<<(irq&7)), imr_port);  +} + + +/* issue a Specific End Of Interrupt instruciton */ +static void specific_eoi(int irq) +{ +	/* If it is on the slave PIC this have to be performed on +	 * both the master and the slave PICs */ +	if (irq > 7) { +		outb(OCW2_SEOI|(irq&7), SLAVE_PIC + OCW2); +		irq = SEOI_IR2;               /* also do IR2 on master */ +	}  +	outb(OCW2_SEOI|irq, MASTER_PIC + OCW2); +} + +void __attribute__ ((regparm(0))) do_irq(int irq)  +{ +	 +	mask_irq(irq); +	 +	if (irq_table[irq].status & IRQ_DISABLED) { +		unmask_irq(irq); +		specific_eoi(irq); +		return; +	} +	 +	 +	if (NULL != irq_table[irq].handler) { +		irq_handler_t *handler; +		for (handler = irq_table[irq].handler;  +		     NULL!= handler; handler = handler->next) { +			handler->isr_func(handler->isr_data); +		} +	} else { +		if ((irq & 7) != 7) {				 +			printf("Spurious irq %d\n", irq); +		} +	}		 +	unmask_irq(irq); +	specific_eoi(irq);	 +} + + +void __attribute__ ((regparm(0))) unknown_exception_entry(int cause, int ip, int seg)  +{ +	printf("Unknown Exception %d at %04x:%08x\n", cause, seg, ip); +} + +void __attribute__ ((regparm(0))) divide_exception_entry(int cause, int ip, int seg)  +{ +	printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); +	while(1); +} + +void __attribute__ ((regparm(0))) debug_exception_entry(int cause, int ip, int seg)  +{ +	printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) nmi_entry(int cause, int ip, int seg)  +{ +	printf("NMI Interrupt at %04x:%08x\n", seg, ip); +} +		 +void __attribute__ ((regparm(0))) invalid_instruction_entry(int cause, int ip, int seg)  +{ +	printf("Invalid Instruction at %04x:%08x\n", seg, ip); +	while(1); +} +				 +void __attribute__ ((regparm(0))) double_fault_entry(int cause, int ip, int seg)  +{ +	printf("Double fault at %04x:%08x\n", seg, ip); +	while(1); +} + +void __attribute__ ((regparm(0))) invalid_tss_exception_entry(int cause, int ip, int seg)  +{ +	printf("Invalid TSS at %04x:%08x\n", seg, ip); +} +		 +void __attribute__ ((regparm(0))) seg_fault_entry(int cause, int ip, int seg)  +{ +	printf("Segmentation fault at %04x:%08x\n", seg, ip); +	while(1); +} + +void __attribute__ ((regparm(0))) stack_fault_entry(int cause, int ip, int seg)  +{ +	printf("Stack fault at %04x:%08x\n", seg, ip); +	while(1); +} + +void __attribute__ ((regparm(0))) gpf_entry(int cause, int ip, int seg)  +{ +	printf("General protection fault at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) page_fault_entry(int cause, int ip, int seg)  +{ +	printf("Page fault at %04x:%08x\n", seg, ip); +	while(1); +} + +void __attribute__ ((regparm(0))) fp_exception_entry(int cause, int ip, int seg)  +{ +	printf("Floating point exception at %04x:%08x\n", seg, ip); +} + +void __attribute__ ((regparm(0))) alignment_check_entry(int cause, int ip, int seg)  +{ +	printf("Alignment check at %04x:%08x\n", seg, ip); +} +        +void __attribute__ ((regparm(0))) machine_check_entry(int cause, int ip, int seg)  +{ +	printf("Machine check exception at %04x:%08x\n", seg, ip); +} + + +void irq_install_handler(int ino, interrupt_handler_t *func, void *pdata) +{ +	int status; +	 +	if (ino>MAX_IRQ) { +		return; +	} +		 +	if (NULL != irq_table[ino].handler) { +		return; +	} +	 +	status = disable_interrupts(); +	irq_table[ino].handler = malloc(sizeof(irq_handler_t)); +	if (NULL == irq_table[ino].handler) { +		return; +	} +	 +	memset(irq_table[ino].handler, 0, sizeof(irq_handler_t)); +	 +	irq_table[ino].handler->isr_func = func; +	irq_table[ino].handler->isr_data = pdata; +	if (status) { +		enable_interrupts(); +	} +	 +	unmask_irq(ino); +	 +	return; +} + +void irq_free_handler(int ino) +{ +	int status; +	if (ino>MAX_IRQ) { +		return; +	} +	 +	status = disable_interrupts(); +	mask_irq(ino); +	if (NULL == irq_table[ino].handler) { +		return; +	} +	free(irq_table[ino].handler); +	irq_table[ino].handler=NULL; +	if (status) { +		enable_interrupts(); +	} +	return; +} + + +asm ("idt_ptr:\n" +	".word	0x800\n" /* size of the table 8*256 bytes */ +	".long	idt\n"	 /* offset */ +	".word	0x18\n");/* data segment */ + +static void set_vector(int intnum, void *routine) +{ +	idt[intnum].base_high = (u16)((u32)(routine)>>16);	 +	idt[intnum].base_low = (u16)((u32)(routine)&0xffff);	 +} + + +int interrupt_init(void) +{ +	int i; +	 +	/* Just in case... */ +	disable_interrupts(); +		 +	/* Initialize the IDT and stuff */ +	 +	 +	memset(irq_table, 0, sizeof(irq_table)); + +	/* Setup the IDT */ +	for (i=0;i<256;i++) {		 +		idt[i].access = 0x8e; +		idt[i].res = 0;	 +		idt[i].selector = 0x10;	 +		set_vector(i, default_isr); +	}	 +	 +	asm ("cs lidt idt_ptr\n"); +	 +	/* Setup exceptions */ +	set_vector(0x00, exp_0); +	set_vector(0x01, exp_1); +	set_vector(0x02, exp_2); +	set_vector(0x03, exp_3); +	set_vector(0x04, exp_4); +	set_vector(0x05, exp_5); +	set_vector(0x06, exp_6); +	set_vector(0x07, exp_7); +	set_vector(0x08, exp_8); +	set_vector(0x09, exp_9); +	set_vector(0x0a, exp_10); +	set_vector(0x0b, exp_11); +	set_vector(0x0c, exp_12); +	set_vector(0x0d, exp_13); +	set_vector(0x0e, exp_14); +	set_vector(0x0f, exp_15); +	set_vector(0x10, exp_16); +	set_vector(0x11, exp_17); +	set_vector(0x12, exp_18); +	set_vector(0x13, exp_19); +	set_vector(0x14, exp_20); +	set_vector(0x15, exp_21); +	set_vector(0x16, exp_22); +	set_vector(0x17, exp_23); +	set_vector(0x18, exp_24); +	set_vector(0x19, exp_25); +	set_vector(0x1a, exp_26); +	set_vector(0x1b, exp_27); +	set_vector(0x1c, exp_28); +	set_vector(0x1d, exp_29); +	set_vector(0x1e, exp_30); +	set_vector(0x1f, exp_31); + + +	/* Setup interrupts */ +	set_vector(0x20, irq_0); +	set_vector(0x21, irq_1); +	set_vector(0x23, irq_3); +	set_vector(0x24, irq_4); +	set_vector(0x25, irq_5); +	set_vector(0x26, irq_6); +	set_vector(0x27, irq_7); +	set_vector(0x28, irq_8); +	set_vector(0x29, irq_9); +	set_vector(0x2a, irq_10); +	set_vector(0x2b, irq_11); +	set_vector(0x2c, irq_12); +	set_vector(0x2d, irq_13); +	set_vector(0x2e, irq_14); +	set_vector(0x2f, irq_15); +	/* vectors 0x30-0x3f are reserved for irq 16-31 */ +	set_vector(0x40, syscall_entry); + +	 +	/* Mask all interrupts */ +	outb(0xff, MASTER_PIC + IMR); +	outb(0xff, SLAVE_PIC + IMR); +	 +	/* Master PIC */ +	outb(ICW1_SEL|ICW1_EICW4, MASTER_PIC + ICW1);	 +	outb(0x20, MASTER_PIC + ICW2);          /* Place master PIC interrupts at INT20 */ +	outb(IR2, MASTER_PIC + ICW3);		/* ICW3, One slevc PIC is present */	 +	outb(ICW4_PM, MASTER_PIC + ICW4); +	 +	for (i=0;i<8;i++) { +		outb(OCW2_SEOI|i, MASTER_PIC + OCW2); +	} +	 +	/* Slave PIC */ +	outb(ICW1_SEL|ICW1_EICW4, SLAVE_PIC + ICW1);	 +	outb(0x28, SLAVE_PIC + ICW2);	        /* Place slave PIC interrupts at INT28 */ +	outb(0x02, SLAVE_PIC + ICW3);		/* Slave ID */ +	outb(ICW4_PM, SLAVE_PIC + ICW4);         +	 +	for (i=0;i<8;i++) { +		outb(OCW2_SEOI|i, SLAVE_PIC + OCW2); +	} +	 +	 +	/* enable cascade interrerupt */ +	outb(0xfb, MASTER_PIC + IMR); +	outb(0xff, SLAVE_PIC + IMR); +	 +	/* It is now safe to enable interrupts */ +	enable_interrupts();  +	 +	return 0; +} + +void enable_interrupts(void) +{ +	asm("sti\n"); +} + +int disable_interrupts(void) +{ +	long flags; +	 +	asm volatile ("pushfl ; popl %0 ; cli\n" : "=g" (flags) : ); +	 +	return (flags&0x200); /* IE flags is bit 9 */ +} + + +#ifdef CFG_RESET_GENERIC + +void __attribute__ ((regparm(0))) generate_gpf(void); +asm(".globl generate_gpf\n"  +    "generate_gpf:\n"  +    "ljmp   $0x70, $0x47114711\n"); /* segment 0x70 is an arbitrary segment which does not  +				    * exist */ +void reset_cpu(ulong addr) +{ +	set_vector(13, generate_gpf);  /* general protection fault handler */ +	set_vector(8, generate_gpf);   /* double fault handler */ +	generate_gpf();                /* start the show */ +} +#endif diff --git a/cpu/i386/reset.S b/cpu/i386/reset.S new file mode 100644 index 000000000..57e32a8b7 --- /dev/null +++ b/cpu/i386/reset.S @@ -0,0 +1,38 @@ +/* + *  U-boot - i386 Startup Code  + * + *  Copyright (c) 2002	Omicron Ceti AB, Daniel Engström <denaiel@omicron.se> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Reset vector, jumps to start16.S */ + +.extern start16 + +.section .reset, "ax" +.code16 +reset_vector:  +        cli +        cld +        jmp start16  + +	.org 0xf +	nop +	 diff --git a/cpu/i386/serial.c b/cpu/i386/serial.c new file mode 100644 index 000000000..c0d2e8aa1 --- /dev/null +++ b/cpu/i386/serial.c @@ -0,0 +1,460 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/*------------------------------------------------------------------------------+ */ +/* + * This source code has been made available to you by IBM on an AS-IS + * basis.  Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications.  No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT   I B M   CORPORATION 1995 + * LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M + */ +/*------------------------------------------------------------------------------- */ + +#include <common.h> +#include <watchdog.h> +#include <asm/io.h> +#include <asm/ibmpc.h> + +#if CONFIG_SERIAL_SOFTWARE_FIFO +#include <malloc.h> +#endif + +#define UART_RBR    0x00 +#define UART_THR    0x00 +#define UART_IER    0x01 +#define UART_IIR    0x02 +#define UART_FCR    0x02 +#define UART_LCR    0x03 +#define UART_MCR    0x04 +#define UART_LSR    0x05 +#define UART_MSR    0x06 +#define UART_SCR    0x07 +#define UART_DLL    0x00 +#define UART_DLM    0x01 + +/*-----------------------------------------------------------------------------+ +  | Line Status Register. +  +-----------------------------------------------------------------------------*/ +#define asyncLSRDataReady1            0x01 +#define asyncLSROverrunError1         0x02 +#define asyncLSRParityError1          0x04 +#define asyncLSRFramingError1         0x08 +#define asyncLSRBreakInterrupt1       0x10 +#define asyncLSRTxHoldEmpty1          0x20 +#define asyncLSRTxShiftEmpty1         0x40 +#define asyncLSRRxFifoError1          0x80 + + + +#if CONFIG_SERIAL_SOFTWARE_FIFO +/*-----------------------------------------------------------------------------+ +  | Fifo +  +-----------------------------------------------------------------------------*/ +typedef struct { +	char *rx_buffer; +	ulong rx_put; +	ulong rx_get; +} serial_buffer_t; + +volatile static serial_buffer_t buf_info; +#endif + + +static int serial_div (int baudrate ) +{ +	 +	switch (baudrate) { +	case 1200: +		return 96; +	case 9600: +		return 12; +	case 19200: +		return 6; +	case 38400: +		return 3; +	case 57600: +		return 2; +	case 115200: +		return 1;		 +	} +	hang (); +} + + +/* + * Minimal serial functions needed to use one of the SMC ports + * as serial console interface. + */ + +int serial_init (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	volatile char val; + +	int bdiv = serial_div(gd->baudrate); +     + +	outb(0x80, UART0_BASE + UART_LCR);	/* set DLAB bit */ +	outb(bdiv, UART0_BASE + UART_DLL);	/* set baudrate divisor */ +	outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */ +	outb(0x03, UART0_BASE + UART_LCR);	/* clear DLAB; set 8 bits, no parity */ +	outb(0x00, UART0_BASE + UART_FCR);	/* disable FIFO */ +	outb(0x00, UART0_BASE + UART_MCR);	/* no modem control DTR RTS */ +	val = inb(UART0_BASE + UART_LSR);	/* clear line status */ +	val = inb(UART0_BASE + UART_RBR);	/* read receive buffer */ +	outb(0x00, UART0_BASE + UART_SCR);	/* set scratchpad */ +	outb(0x00, UART0_BASE + UART_IER);	/* set interrupt enable reg */ + +	return (0); +} + + +void serial_setbrg (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	unsigned short bdiv; +	 +	bdiv = serial_div (gd->baudrate); + +	outb(0x80, UART0_BASE + UART_LCR);	/* set DLAB bit */ +	outb(bdiv&0xff, UART0_BASE + UART_DLL);	/* set baudrate divisor */ +	outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */ +	outb(0x03, UART0_BASE + UART_LCR);	/* clear DLAB; set 8 bits, no parity */ +} + + +void serial_putc (const char c) +{ +	int i; + +	if (c == '\n') +		serial_putc ('\r'); + +	/* check THRE bit, wait for transmiter available */ +	for (i = 1; i < 3500; i++) { +		if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20) +			break; +		udelay (100); +	} +	outb(c, UART0_BASE + UART_THR);	/* put character out */ +} + + +void serial_puts (const char *s) +{ +	while (*s) { +		serial_putc (*s++); +	} +} + + +int serial_getc () +{ +	unsigned char status = 0; + +	while (1) { +#if defined(CONFIG_HW_WATCHDOG) +		WATCHDOG_RESET ();	/* Reset HW Watchdog, if needed */ +#endif	/* CONFIG_HW_WATCHDOG */ +		status = inb (UART0_BASE + UART_LSR); +		if ((status & asyncLSRDataReady1) != 0x0) { +			break; +		} +		if ((status & ( asyncLSRFramingError1 | +				asyncLSROverrunError1 | +				asyncLSRParityError1  | +				asyncLSRBreakInterrupt1 )) != 0) { +			outb(asyncLSRFramingError1 | +			      asyncLSROverrunError1 | +			      asyncLSRParityError1  | +			      asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR); +		} +	} +	return (0x000000ff & (int) inb (UART0_BASE)); +} + + +int serial_tstc () +{ +	unsigned char status; + +	status = inb (UART0_BASE + UART_LSR); +	if ((status & asyncLSRDataReady1) != 0x0) { +		return (1); +	} +	if ((status & ( asyncLSRFramingError1 | +			asyncLSROverrunError1 | +			asyncLSRParityError1  | +			asyncLSRBreakInterrupt1 )) != 0) { +		outb(asyncLSRFramingError1 | +		      asyncLSROverrunError1 | +		      asyncLSRParityError1  | +		      asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR); +	} +	return 0; +} + + +#if CONFIG_SERIAL_SOFTWARE_FIFO + +void serial_isr (void *arg) +{ +	int space; +	int c; +	const int rx_get = buf_info.rx_get; +	int rx_put = buf_info.rx_put; + +	if (rx_get <= rx_put) { +		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get); +	} else { +		space = rx_get - rx_put; +	} +	while (serial_tstc ()) { +		c = serial_getc (); +		if (space) { +			buf_info.rx_buffer[rx_put++] = c; +			space--; +		} +		if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) +			rx_put = 0; +		if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) { +			/* Stop flow by setting RTS inactive */ +			outb(inb (UART0_BASE + UART_MCR) & (0xFF ^ 0x02), +			      UART0_BASE + UART_MCR); +		} +	} +	buf_info.rx_put = rx_put; +} + +void serial_buffered_init (void) +{ +	serial_puts ("Switching to interrupt driven serial input mode.\n"); +	buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO); +	buf_info.rx_put = 0; +	buf_info.rx_get = 0; + +	if (inb (UART0_BASE + UART_MSR) & 0x10) { +		serial_puts ("Check CTS signal present on serial port: OK.\n"); +	} else { +		serial_puts ("WARNING: CTS signal not present on serial port.\n"); +	} + +	irq_install_handler ( VECNUM_U0 /*UART0 *//*int vec */ , +			      serial_isr /*interrupt_handler_t *handler */ , +			      (void *) &buf_info /*void *arg */ ); + +	/* Enable "RX Data Available" Interrupt on UART */ +	/* outb(inb(UART0_BASE + UART_IER) |0x01, UART0_BASE + UART_IER); */ +	outb(0x01, UART0_BASE + UART_IER); +	/* Set DTR active */ +	outb(inb (UART0_BASE + UART_MCR) | 0x01, UART0_BASE + UART_MCR); +	/* Start flow by setting RTS active */ +	outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR); +	/* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */ +	outb((1 << 6) | 1, UART0_BASE + UART_FCR); +} + +void serial_buffered_putc (const char c) +{ +	/* Wait for CTS */ +#if defined(CONFIG_HW_WATCHDOG) +	while (!(inb (UART0_BASE + UART_MSR) & 0x10)) +		WATCHDOG_RESET (); +#else +	while (!(inb (UART0_BASE + UART_MSR) & 0x10)); +#endif +	serial_putc (c); +} + +void serial_buffered_puts (const char *s) +{ +	serial_puts (s); +} + +int serial_buffered_getc (void) +{ +	int space; +	int c; +	int rx_get = buf_info.rx_get; +	int rx_put; + +#if defined(CONFIG_HW_WATCHDOG) +	while (rx_get == buf_info.rx_put) +		WATCHDOG_RESET (); +#else +	while (rx_get == buf_info.rx_put); +#endif +	c = buf_info.rx_buffer[rx_get++]; +	if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO) +		rx_get = 0; +	buf_info.rx_get = rx_get; + +	rx_put = buf_info.rx_put; +	if (rx_get <= rx_put) { +		space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get); +	} else { +		space = rx_get - rx_put; +	} +	if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) { +		/* Start flow by setting RTS active */ +		outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR); +	} + +	return c; +} + +int serial_buffered_tstc (void) +{ +	return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0; +} + +#endif	/* CONFIG_SERIAL_SOFTWARE_FIFO */ + + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +/* +  AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port +  number 0 or number 1 +  - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 : +  configuration has been already done +  - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 : +  configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE +*/ +#if (CONFIG_KGDB_SER_INDEX & 2) +void kgdb_serial_init (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	volatile char val; +	bdiv = serial_div (CONFIG_KGDB_BAUDRATE); + +	/* +	 * Init onboard 16550 UART +	 */ +	outb(0x80, UART1_BASE + UART_LCR);	/* set DLAB bit */ +	outb(bdiv & 0xff), UART1_BASE + UART_DLL);	/* set divisor for 9600 baud */ +	outb(bdiv >> 8), UART1_BASE + UART_DLM);	/* set divisor for 9600 baud */ +	outb(0x03, UART1_BASE + UART_LCR);	/* line control 8 bits no parity */ +	outb(0x00, UART1_BASE + UART_FCR);	/* disable FIFO */ +	outb(0x00, UART1_BASE + UART_MCR);	/* no modem control DTR RTS */ +	val = inb(UART1_BASE + UART_LSR);	/* clear line status */ +	val = inb(UART1_BASE + UART_RBR);	/* read receive buffer */ +	outb(0x00, UART1_BASE + UART_SCR);	/* set scratchpad */ +	outb(0x00, UART1_BASE + UART_IER);	/* set interrupt enable reg */ +} + + +void putDebugChar (const char c) +{ +	if (c == '\n') +		serial_putc ('\r'); + +	outb(c, UART1_BASE + UART_THR);	/* put character out */ + +	/* check THRE bit, wait for transfer done */ +	while ((inb(UART1_BASE + UART_LSR) & 0x20) != 0x20); +} + + +void putDebugStr (const char *s) +{ +	while (*s) { +		serial_putc(*s++); +	} +} + + +int getDebugChar (void) +{ +	unsigned char status = 0; + +	while (1) { +		status = inb(UART1_BASE + UART_LSR); +		if ((status & asyncLSRDataReady1) != 0x0) { +			break; +		} +		if ((status & ( asyncLSRFramingError1 | +				asyncLSROverrunError1 | +				asyncLSRParityError1  | +				asyncLSRBreakInterrupt1 )) != 0) { +			outb(asyncLSRFramingError1 | +			     asyncLSROverrunError1 | +			     asyncLSRParityError1  | +			     asyncLSRBreakInterrupt1, UART1_BASE + UART_LSR); +		} +	} +	return (0x000000ff & (int) inb(UART1_BASE)); +} + + +void kgdb_interruptible (int yes) +{ +	return; +} + +#else	/* ! (CONFIG_KGDB_SER_INDEX & 2) */ + +void kgdb_serial_init (void) +{ +	serial_printf ("[on serial] "); +} + +void putDebugChar (int c) +{ +	serial_putc (c); +} + +void putDebugStr (const char *str) +{ +	serial_puts (str); +} + +int getDebugChar (void) +{ +	return serial_getc (); +} + +void kgdb_interruptible (int yes) +{ +	return; +} +#endif	/* (CONFIG_KGDB_SER_INDEX & 2) */ +#endif	/* CFG_CMD_KGDB */ + diff --git a/cpu/i386/start.S b/cpu/i386/start.S new file mode 100644 index 000000000..025555c0a --- /dev/null +++ b/cpu/i386/start.S @@ -0,0 +1,198 @@ +/* + *  U-boot - i386 Startup Code  + * + *  Copyright (c) 2002	Omicron Ceti AB, Daniel Engström <denaiel@omicron.se> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <config.h> +#include <version.h> + +	 +.section .text +.code32 +.globl _start +.type _start, @function	 +.globl _i386boot_start +_i386boot_start: +_start:		 +        movl    $0x18,%eax         	/* Load our segement registes, the +                                         * gdt have already been loaded by start16.S */ +        movw    %ax,%fs +	movw	%ax,%ds +        movw    %ax,%gs +        movw    %ax,%es +        movw    %ax,%ss +	 +	/* We call a few functions in the board support package +	 * since we have no stack yet we'll have to use %ebp +	 * to store the return address */ +	 +	/* Early platform init (setup gpio, etc ) */ +	mov     $early_board_init_ret, %ebp +	jmp	early_board_init +early_board_init_ret: +	 +	/* The __port80 entry-point should be usabe by now */ +	/* so we try to indicate progress */ +	movw	$0x01, %ax     +	movl	$.progress0, %ebp +	jmp	__show_boot_progress +.progress0:  	 + +	/* size memory */ +	mov	$mem_init_ret, %ebp +	jmp     mem_init		 +mem_init_ret: +	 +	/* check ammount of configured memory  +	 * (we need atleast bss start+bss size+stack size) */		 +	movl	$_i386boot_bss_start, %ecx        /* BSS start */ +	addl	$_i386boot_bss_size, %ecx         /* BSS size */	 +	addl	$CFG_STACK_SIZE, %ecx +	cmpl	%ecx, %eax  +	jae	mem_ok +	 +	/* indicate (lack of) progress */ +	movw	$0x81, %ax     +	movl	$.progress0a, %ebp +	jmp	__show_boot_progress +.progress0a:  	 +	jmp 	die +mem_ok:	 + +	/* indicate progress */ +	movw	$0x02, %ax     +	movl	$.progress1, %ebp +	jmp	__show_boot_progress +.progress1:  	 + +	/* create a stack after the bss */ +        movl    $_i386boot_bss_start, %eax +	addl	$_i386boot_bss_size, %eax +	addl	$CFG_STACK_SIZE, %eax +        movl    %eax, %esp +	 +	pushl	$0 +	popl	%eax +	cmpl	$0, %eax +	jne	no_stack +	push	$0x55aa55aa +	popl	%ebx +	cmpl	$0x55aa55aa, %ebx +	je	stack_ok + +no_stack: +	/* indicate (lack of) progress */ +	movw	$0x82, %ax     +	movl	$.progress1a, %ebp +	jmp	__show_boot_progress +.progress1a:  	 +	jmp die +	 +	 +stack_ok:	 +	/* indicate progress */ +	movw	$0x03, %ax     +	movl	$.progress2, %ebp +	jmp	__show_boot_progress +.progress2:  	 + +	/* copy data section to ram, size must be 4-byte aligned */ +	movl	$_i386boot_romdata_dest, %edi	  /* destination address */ + 	movl	$_i386boot_romdata_start, %esi	  /* source address */ +	movl	$_i386boot_romdata_size, %ecx     /* number of bytes to copy */ +	movl	%ecx, %eax +	andl	$3, %eax +	jnz	data_fail +	 +	shrl	$2, %ecx	                  /* copy 4 byte each time */ +	cld	  +	cmpl	$0, %ecx +	je	data_ok	 +data_segment:	 +	movsl		 +	loop	data_segment +	jmp	data_ok +data_fail: +	/* indicate (lack of) progress */ +	movw	$0x83, %ax     +	movl	$.progress2a, %ebp +	jmp	__show_boot_progress +.progress2a:  	 +	jmp 	die + +data_ok:	 + +	/* indicate progress */ +	movw	$0x04, %ax     +	movl	$.progress3, %ebp +	jmp	__show_boot_progress +.progress3:  	 + +	/* clear bss section in ram, size must be 4-byte aligned  */ +	movl	$_i386boot_bss_start, %eax        /* BSS start */ +	movl	$_i386boot_bss_size, %ecx         /* BSS size */	 +	movl	%ecx, %eax +	andl	$3, %eax +	jnz	bss_fail +	shrl	$2, %ecx	                  /* clear 4 byte each time */ +	cld		       +	cmpl	$0, %ecx +	je	bss_ok	 +bss:	 +	movl	$0, (%edi) +	add	$4, %edi			 +	loop	bss +	jmp 	bss_ok + +bss_fail: +	/* indicate (lack of) progress */ +	movw	$0x84, %ax     +	movl	$.progress3a, %ebp +	jmp	__show_boot_progress +.progress3a:  	 +	jmp 	die + +bss_ok:	 + +	wbinvd	  + + +	/* indicate progress */ +	movw	$0x05, %ax     +	movl	$.progress4, %ebp +	jmp	__show_boot_progress +.progress4: + +	call	start_i386boot  /* Enter, U-boot! */ + +	/* indicate (lack of) progress */ +	movw	$0x85, %ax     +	movl	$.progress4a, %ebp +	jmp	__show_boot_progress +.progress4a: + +die:	hlt +	jmp	die +	hlt                      + + diff --git a/cpu/i386/start16.S b/cpu/i386/start16.S new file mode 100644 index 000000000..590a5a6c9 --- /dev/null +++ b/cpu/i386/start16.S @@ -0,0 +1,112 @@ +/* + *  U-boot - i386 Startup Code  + * + *  Copyright (c) 2002	Omicron Ceti AB, Daniel Engström <denaiel@omicron.se> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#define BOOT_SEG	0xffff0000	/* linear segment of boot code */ +#define a32		.byte 0x67; +#define o32		.byte 0x66; + +.section .start16, "ax" +.code16 +.globl start16 +start16:  +	/* First we let the BSP do some early initialization +	 * this code have to map the flash to its final position +	 */ +	mov	$board_init16_ret, %bp +	jmp	board_init16 +board_init16_ret:	 +	 +	/* Turn of cache (this might require a 486-class CPU) */ +        movl    %cr0, %eax +        orl     $060000000,%eax +        movl    %eax, %cr0 +        wbinvd  		      +	 +	/* load the descriptor tables */ +o32 cs	lidt	idt_ptr +o32 cs	lgdt    gdt_ptr		  + + +	/* Now, we enter protected mode */ +        movl    %cr0, %eax                +        orl     $1,%eax                   +        movl    %eax, %cr0             +	 +	/* Flush the prefetch queue */ +        jmp     ff         +ff: + +	/* Finally jump to the 32bit initialization code */ +	movw	$code32start, %ax  +        movw    %ax,%bp +o32 cs	ljmp	*(%bp) + +	/* 48-bit far pointer */ +code32start: +	.long	_start                          /* offset */ +	.word	0x10                            /* segment */ + +idt_ptr: +	.word	0				/* limit */ +	.long	0		       		/* base */ +	 +gdt_ptr: +	.word	0x30			        /* limit (48 bytes = 6 GDT entries) */ +	.long	BOOT_SEG + gdt	        	/* base */ + +	/* The GDT table ...  +	 * +	 *       Selector	Type  +	 * 	 0x00		NULL +	 * 	 0x08		Unused +	 *	 0x10		32bit code  +	 *	 0x18		32bit data/stack +	 *	 0x20		16bit code +	 *	 0x28	 	16bit data/stack +	 */ + +gdt: +	.word	0, 0, 0, 0			/* NULL  */ +	.word	0, 0, 0, 0			/* unused */ + +	.word	0xFFFF				/* 4Gb - (0x100000*0x1000 = 4Gb) */ +	.word	0				/* base address = 0 */ +	.word	0x9B00				/* code read/exec */ +	.word	0x00CF				/* granularity = 4096, 386 (+5th nibble of limit) */ + +	.word	0xFFFF				/* 4Gb - (0x100000*0x1000 = 4Gb) */ +	.word	0x0				/* base address = 0 */ +	.word	0x9300				/* data read/write */ +	.word	0x00CF				/* granularity = 4096, 386 (+5th nibble of limit) */ +						 +	.word	0xFFFF				/* 64kb */ +	.word	0				/* base address = 0 */ +	.word	0x9b00				/* data read/write */ +	.word	0x0010				/* granularity = 1  (+5th nibble of limit) */ +	 +	.word	0xFFFF				/* 64kb */ +	.word	0				/* base address = 0 */ +	.word	0x9300				/* data read/write */ +	.word	0x0010				/* granularity = 1 (+5th nibble of limit) */ diff --git a/cpu/i386/timer.c b/cpu/i386/timer.c new file mode 100644 index 000000000..a23cd6e48 --- /dev/null +++ b/cpu/i386/timer.c @@ -0,0 +1,211 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/i8254.h> +#include <asm/ibmpc.h> + + +static volatile unsigned long system_ticks; +static int timer_init_done =0; + +static void timer_isr(void *unused) +{ +	system_ticks++; +} + +unsigned long get_system_ticks(void) +{ +	return system_ticks; +} + +#define TIMER0_VALUE 0x04aa /* 1kHz 1.9318MHz / 1000 */ +#define TIMER2_VALUE 0x0a8e /* 440Hz */ + +int timer_init(void) +{ +	system_ticks = 0; +	 +	irq_install_handler(0, timer_isr, NULL); +	 +	/* initialize timer 0 and 2  +	 *  +	 * Timer 0 is used to increment system_tick 1000 times/sec +	 * Timer 1 was used for DRAM refresh in early PC's +	 * Timer 2 is used to drive the speaker +	 * (to stasrt a beep: write 3 to port 0x61, +	 * to stop it again: write 0) +	 */ +		 +        outb(PIT_CMD_CTR0|PIT_CMD_BOTH|PIT_CMD_MODE2, PIT_BASE + PIT_COMMAND); +	outb(TIMER0_VALUE&0xff, PIT_BASE + PIT_T0); +	outb(TIMER0_VALUE>>8, PIT_BASE + PIT_T0); + +        outb(PIT_CMD_CTR2|PIT_CMD_BOTH|PIT_CMD_MODE3, PIT_BASE + PIT_COMMAND); +	outb(TIMER2_VALUE&0xff, PIT_BASE + PIT_T2); +	outb(TIMER2_VALUE>>8, PIT_BASE + PIT_T2); + +	timer_init_done = 1; +	 +	return 0; +} + + +#ifdef CFG_TIMER_GENERIC + +/* the unit for these is CFG_HZ */ + +/* FixMe: implement these */ +void reset_timer (void) +{ +	system_ticks = 0; +} + +ulong get_timer (ulong base) +{ +	return (system_ticks - base); +} + +void set_timer (ulong t)	 +{ +	system_ticks = t; +} + +static u16 read_pit(void) +{ +	u8 low; +	outb(PIT_CMD_LATCH, PIT_BASE + PIT_COMMAND); +	low = inb(PIT_BASE + PIT_T0); +	return ((inb(PIT_BASE + PIT_T0) << 8) | low); +} + +/* this is not very exact */ +void udelay (unsigned long usec) +{	 +	int counter; +	int wraps; +	 +	if (!timer_init_done) { +		return; +	} +	counter = read_pit(); +	wraps = usec/1000; +	usec = usec%1000; +	 +	usec*=1194; +	usec/=1000; +	usec+=counter;  +	if (usec > 1194) { +		usec-=1194; +		wraps++; +	} + +	while (1) { +		int new_count = read_pit(); +		 +		if (((new_count < usec) && !wraps) || wraps < 0) { +			break; +		} +		 +		if (new_count > counter) { +			wraps--; +		} +		counter = new_count; +	} +	 +} + +#if 0 +/* this is a version with debug output */ +void _udelay (unsigned long usec) +{	 +	int counter; +	int wraps; +	 +	int usec1, usec2, usec3; +	int wraps1, wraps2, wraps3, wraps4; +	int ctr1, ctr2, ctr3, nct1, nct2; +	int i; +	usec1=usec; +	if (!timer_init_done) { +		return; +	} +	counter = read_pit(); +	ctr1 = counter; +	wraps = usec/1000; +	usec = usec%1000; +	 +	usec2 = usec; +	wraps1 = wraps; +	 +	usec*=1194; +	usec/=1000; +	usec+=counter;  +	if (usec > 1194) { +		usec-=1194; +		wraps++; +	} + +	usec3 = usec; +	wraps2 = wraps; +	 +	ctr2 = wraps3 = nct1 = 4711; +	ctr3 = wraps4 = nct2 = 4711; +	i=0; +	while (1) { +		int new_count = read_pit(); +		i++; +		if ((new_count < usec && !wraps) || wraps < 0) { +			break; +		} +		 +		if (new_count > counter) { +			wraps--; +		} +		if (ctr2==4711) { +			ctr2 = counter; +			wraps3 = wraps; +			nct1 = new_count; +		} else { +			ctr3 = counter; +			wraps4 = wraps; +			nct2 = new_count; +		} +		 +		counter = new_count; +	} +	 +	printf("udelay(%d)\n", usec1); +	printf("counter %d\n", ctr1); +	printf("1: wraps %d, usec %d\n", wraps1, usec2); +	printf("2: wraps %d, usec %d\n", wraps2, usec3); +	printf("new_count[0] %d counter %d wraps %d\n", nct1, ctr2, wraps3); +	printf("new_count[%d] %d counter %d wraps %d\n", i, nct2, ctr3, wraps4); + +	printf("%d %d %d %d %d\n", +	       read_pit(), read_pit(), read_pit(), +	       read_pit(), read_pit()); +} +#endif +#endif diff --git a/doc/README-i386 b/doc/README-i386 new file mode 100644 index 000000000..99b3e198c --- /dev/null +++ b/doc/README-i386 @@ -0,0 +1,74 @@ +This is my attempt to port PPCBoot to the i386 platform. This +work was sponsored by my emplyer, Omicron Ceti AB. http://www.omicron.se + +It is currently capable of booting a linux bzImage from flash on +the AMD SC520 CDP platform. + +It was originally based on PPCBoot taken from the CVS October 28 2002.   + +To compile: + +1) Unpack the source tree, either from the complete tarball or +   from the virgin snapshot + the patch +    +2) Configure the source +   $ make sc520_cdp_comfig +   $ make +    +To use this code on the CDP: +1) Make a suitable kernel, I used 2.4.19 with the mtd-support updated +   from the MTD CVS and a patch to allow root=/dev/mtdblock1 which I +   included at the end of this file.  +   The following options in the MTD section might be useful: +    +   CONFIG_MTD_PHYSMAP=y +   CONFIG_MTD_PHYSMAP_START=38100000 +   CONFIG_MTD_PHYSMAP_LEN=7a0000 +   CONFIG_MTD_PHYSMAP_BUSWIDTH=2 + + +2) Program it in to the CDP flashbank with remon +   ppcboot.bin should be programmed att offset 0x7e000 and the kernel at +   offset 0. If you want to use a jffs2 root file system (not included here),  +   it should be  programmed to offset 0x100000. +    +   remon> z +   remon> yi +   remon> ns ppcboot.bin 7e0000 +   remon> ns bzImage 0 +   remon> ns image.jffs2 100000 + +3) Connect a terminal to the 25pin serial port at 9600bps, and start the CDP. +    +   remon> z +   remon> g + +4) PPCboot should output some message and a prompt on the terminal, to +   start the kernel issue the following command: +    +   BOOT> bootm +    +5) The kernel should boot, and mount the root filesystem if present. + +We hope you find this stuff useful +Daniel Engström, Omicron Ceti AB, daniel@omicron.se + + + +--- linux-2.4.19-orig/init/do_mounts.c	Sat Aug  3 02:39:46 2002 ++++ linux-2.4.19/init/do_mounts.c	Mon Sep 23 16:21:33 2002 +@@ -224,6 +224,14 @@ + 	{ "ftlc", 0x2c10 }, + 	{ "ftld", 0x2c18 }, + 	{ "mtdblock", 0x1f00 }, ++	{ "mtdblock0", 0x1f00 }, ++	{ "mtdblock1", 0x1f01 }, ++	{ "mtdblock2", 0x1f02 }, ++	{ "mtdblock3", 0x1f03 }, ++	{ "mtdblock4", 0x1f04 }, ++	{ "mtdblock5", 0x1f05 }, ++	{ "mtdblock6", 0x1f06 }, ++	{ "mtdblock7", 0x1f07 }, + 	{ NULL, 0 } + }; +  diff --git a/doc/TODO-i386 b/doc/TODO-i386 new file mode 100644 index 000000000..0969cbcd5 --- /dev/null +++ b/doc/TODO-i386 @@ -0,0 +1,39 @@ +i386 port missing features: +* i386 cleaness (wbinvld is 486+ ... ) +* Pentium TSC timer/udelay +* setup the BIOS data area and BIOS equipment word to reflect machine config.  +* Make reset work (from Linux and from the boot prompt) +* DMA, FDC, RTC, KBC initialization +* video card support (call BIOS to initialize, use helper routrine in BSP to shadow  +  video rom if on pci) and PC keyboard +* split of part of cpu/i386/interrupt.c to cpu/i385/entry.c? +* re-entry of protected mode from real mode, should be added to realmode_switch.S  +  (and used by INT 10h and INT 16h handlers for console I/O during early +   linux boot...)  +* missing functions in lib_i386 and cpu/i386 +* speaker beep interface + +i386 port bugs: +* IDE does not work  + +SC520 missing features: +* Watchdog +* SC520 timer/udelay +* SC520 3rd PIC +* SC520 ICE serial +* SC520 MMCR reset  + +SC520 CDP board support missing features: +* Synchronius serial port and seriel EEPROM +* environment in SEEP +* environment in flash +* environment in sram +* status LED ? +* flash driver + +SC520 CDP board support bugs: +* 0x680 LEDS dos not work for me +* is it possible to make both the internal serial ports and the  +  ports on the sio work at the same time? +* ali sio cio lines? +* On-borad ethernet does not work from Linux diff --git a/drivers/pcnet.c b/drivers/pcnet.c index f69cd2ce7..1ba7d817a 100644 --- a/drivers/pcnet.c +++ b/drivers/pcnet.c @@ -288,8 +288,8 @@ static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr)  	unsigned int val;  	val = pcnet_read_csr(dev, i+12) & 0x0ffff;  	/* There may be endianness issues here. */ -	dev->dev_addr[2*i] = val & 0x0ff; -	dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff; +	dev->enetaddr[2*i  ] =  val       & 0x0ff; +	dev->enetaddr[2*i+1] = (val >> 8) & 0x0ff;      }  #endif /* PCNET_HAS_PROM */ @@ -349,7 +349,7 @@ static int pcnet_init(struct eth_device* dev, bd_t *bis)  	lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]);  	lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ);  	lp->rx_ring[i].status = cpu_to_le16(0x8000); -	DEBUG1("Rx%d: base=0x%x buf_length=0x%x status=0x%x\n", +	DEBUG1("Rx%d: base=0x%x buf_length=0x%hx status=0x%hx\n",  	       i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length,  	       lp->rx_ring[i].status);      } diff --git a/examples/syscall.S b/examples/syscall.S index 9e8725edc..993449043 100644 --- a/examples/syscall.S +++ b/examples/syscall.S @@ -38,12 +38,26 @@ mon_free:  	sub     fp, ip, #4  	ldmea   fp, {fp, sp, pc}  #else /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ + +#ifdef CONFIG_I386 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +#define SYMBOL_NAME(X) 	X +#define SYMBOL_NAME_LABEL(X) 	X##: +	 +#define SYSCALL(name,n) \ +	.globl SYMBOL_NAME(name) ; \ +SYMBOL_NAME_LABEL(name)     		 ; \ +	ret + +#endif	/* CONFIG_I386 */ + +#ifdef CONFIG_PPC  #define SYSCALL(name,n) \  	.globl name		; \  name:				; \  	li r0,n			; \  	sc			; \  	blr +#endif	/* CONFIG_PPC */  	.text diff --git a/fs/Makefile b/fs/Makefile index 9ed0f1e5a..ad74942d0 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -22,7 +22,7 @@  #  # -SUBDIRS	:= jffs2 +SUBDIRS	:= jffs2 fdos  .depend all:  	@for dir in $(SUBDIRS) ; do \ diff --git a/fs/fdos/Makefile b/fs/fdos/Makefile new file mode 100644 index 000000000..af0fff1c8 --- /dev/null +++ b/fs/fdos/Makefile @@ -0,0 +1,49 @@ +# +# (C) Copyright 2002 +# Stäubli Faverges - <www.staubli.com> +# Pierre AUBERT  p.aubert@staubli.com +# +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= libfdos.a + +AOBJS	= +COBJS	= fat.o vfat.o dev.o fdos.o fs.o subdir.o  +OBJS	= $(AOBJS) $(COBJS) + +#CPPFLAGS += + +all:	$(LIB) $(AOBJS) + +$(LIB):	.depend $(OBJS) +	$(AR) crv $@ $(OBJS) + + +######################################################################### + +.depend:	Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/fs/fdos/dev.c b/fs/fdos/dev.c new file mode 100644 index 000000000..f38d07dbd --- /dev/null +++ b/fs/fdos/dev.c @@ -0,0 +1,195 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> + +#include "dos.h" +#include "fdos.h" + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#define NB_HEADS        2 +#define NB_TRACKS       80 +#define NB_SECTORS      18 + + +static int lastwhere; + +/*----------------------------------------------------------------------------- + * dev_open --  + *----------------------------------------------------------------------------- + */ +int dev_open (void) +{ +    lastwhere = 0; +    return (0); +} + +/*----------------------------------------------------------------------------- + * dev_read -- len and where are sectors number + *----------------------------------------------------------------------------- + */ +int dev_read (void *buffer, int where, int len) +{ +    PRINTF ("dev_read (len = %d, where = %d)\n", len, where); + +    /* Si on ne desire pas lire a la position courante, il faut un seek      */ +    if (where != lastwhere) { +        if (!fdc_fdos_seek (where)) { +            PRINTF ("seek error in dev_read"); +            lastwhere = -1; +            return (-1); +        } +    } +     +    if (!fdc_fdos_read (buffer, len)) { +        PRINTF ("read error\n"); +        lastwhere = -1; +        return (-1); +    } +    lastwhere = where + len; +    return (0); +} +/*----------------------------------------------------------------------------- + * check_dev -- verify the diskette format + *----------------------------------------------------------------------------- + */ +int check_dev (BootSector_t *boot, Fs_t *fs) +{ +    unsigned int heads, sectors, tracks; +    int BootP, Infp0, InfpX, InfTm; +    int sect_per_track; + +    /* Display Boot header                                                   */ +    PRINTF ("Jump to boot code                  0x%02x 0x%02x 0x%02x\n", +            boot -> jump [0], boot -> jump [1], boot -> jump[2]); +    PRINTF ("OEM name & version                 '%*.*s'\n", +            BANNER_LG, BANNER_LG, boot -> banner ); +    PRINTF ("Bytes per sector hopefully 512     %d\n", +            __le16_to_cpu (boot -> secsiz)); +    PRINTF ("Cluster size in sectors            %d\n", +            boot -> clsiz); +    PRINTF ("Number of reserved (boot) sectors  %d\n", +            __le16_to_cpu (boot -> nrsvsect)); +    PRINTF ("Number of FAT tables hopefully 2   %d\n", +            boot -> nfat); +    PRINTF ("Number of directory slots          %d\n", +            __le16_to_cpu (boot -> dirents)); +    PRINTF ("Total sectors on disk              %d\n", +            __le16_to_cpu (boot -> psect)); +    PRINTF ("Media descriptor=first byte of FAT %d\n", +            boot -> descr); +    PRINTF ("Sectors in FAT                     %d\n", +            __le16_to_cpu (boot -> fatlen)); +    PRINTF ("Sectors/track                      %d\n", +            __le16_to_cpu (boot -> nsect)); +    PRINTF ("Heads                              %d\n", +            __le16_to_cpu (boot -> nheads)); +    PRINTF ("number of hidden sectors           %d\n", +            __le32_to_cpu (boot -> nhs)); +    PRINTF ("big total sectors                  %d\n", +            __le32_to_cpu (boot -> bigsect)); +    PRINTF ("physical drive ?                   %d\n", +            boot -> physdrive); +    PRINTF ("reserved                           %d\n", +            boot -> reserved); +    PRINTF ("dos > 4.0 diskette                 %d\n", +            boot -> dos4); +    PRINTF ("serial number                      %d\n", +            __le32_to_cpu (boot -> serial)); +    PRINTF ("disk label                         %*.*s\n", +            LABEL_LG, LABEL_LG, boot -> label); +    PRINTF ("FAT type                           %8.8s\n", +            boot -> fat_type); +    PRINTF ("reserved by 2M                     %d\n", +            boot -> res_2m); +    PRINTF ("2M checksum (not used)             %d\n", +            boot -> CheckSum); +    PRINTF ("2MF format version                 %d\n", +            boot -> fmt_2mf); +    PRINTF ("1 if write track after format      %d\n", +            boot -> wt); +    PRINTF ("data transfer rate on track 0      %d\n", +            boot -> rate_0); +    PRINTF ("data transfer rate on track<>0     %d\n", +            boot -> rate_any); +    PRINTF ("offset to boot program             %d\n", +            __le16_to_cpu (boot -> BootP)); +    PRINTF ("T1: information for track 0        %d\n", +            __le16_to_cpu (boot -> Infp0)); +    PRINTF ("T2: information for track<>0       %d\n", +            __le16_to_cpu (boot -> InfpX)); +    PRINTF ("T3: track sectors size table       %d\n", +            __le16_to_cpu (boot -> InfTm)); +    PRINTF ("Format date                        0x%04x\n", +            __le16_to_cpu (boot -> DateF)); +    PRINTF ("Format time                        0x%04x\n", +            __le16_to_cpu (boot -> TimeF)); +     + +    /* informations are extracted from boot sector                           */ +    heads = __le16_to_cpu (boot -> nheads); +    sectors = __le16_to_cpu (boot -> nsect); +    fs -> tot_sectors = __le32_to_cpu (boot -> bigsect); +    if (__le16_to_cpu (boot -> psect) != 0) { +        fs -> tot_sectors = __le16_to_cpu (boot -> psect); +    } +     +    sect_per_track = heads * sectors; +    tracks = (fs -> tot_sectors + sect_per_track - 1) / sect_per_track; +     +    BootP = __le16_to_cpu (boot -> BootP); +    Infp0 = __le16_to_cpu (boot -> Infp0); +    InfpX = __le16_to_cpu (boot -> InfpX); +    InfTm = __le16_to_cpu (boot -> InfTm); +     +    if (boot -> dos4 == EXTENDED_BOOT && +        strncmp( boot->banner,"2M", 2 ) == 0 && +        BootP < SZ_STD_SECTOR && +        Infp0 < SZ_STD_SECTOR && +        InfpX < SZ_STD_SECTOR && +        InfTm < SZ_STD_SECTOR && +        BootP >= InfTm + 2 && +        InfTm >= InfpX && +        InfpX >= Infp0 &&  +        Infp0 >= 76 ) { + +        return (-1); +    } + +    if (heads != NB_HEADS || +        tracks != NB_TRACKS || +        sectors != NB_SECTORS || +        __le16_to_cpu (boot -> secsiz) != SZ_STD_SECTOR || +        fs -> tot_sectors == 0 || +        (fs -> tot_sectors % sectors) != 0) { +        return (-1); +    } +     +    return (0); +} + + +#endif diff --git a/fs/fdos/dos.h b/fs/fdos/dos.h new file mode 100644 index 000000000..71701c9fb --- /dev/null +++ b/fs/fdos/dos.h @@ -0,0 +1,177 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _DOS_H_ +#define _DOS_H_ + +/* Definitions for Dos diskettes                                             */ + +/* General definitions                                                       */ +#define SZ_STD_SECTOR   512             /* Standard sector size              */ +#define MDIR_SIZE	32		/* Direntry size                     */ +#define FAT_BITS        12              /* Diskette use 12 bits fat          */ + +#define MAX_PATH	128		/* Max size of the MSDOS PATH        */ +#define MAX_DIR_SECS	64		/* Taille max d'un repertoire (en    */ +                                        /* secteurs)                         */ +/* Misc. definitions                                                         */ +#define DELMARK         '\xe5' +#define EXTENDED_BOOT   (0x29) +#define MEDIA_STD       (0xf0) +#define JUMP_0_1        (0xe9) +#define JUMP_0_2        (0xeb) + +/* Boot size is 256 bytes, but we need to read almost a sector, then +   assume bootsize is 512                                                    */ +#define BOOTSIZE        512 + +/* Fat definitions for 12 bits fat                                           */ +#define FAT12_MAX_NB    4086 +#define FAT12_LAST      0x0ff6 +#define FAT12_END       0x0fff + +/* file attributes                                                           */ +#define ATTR_READONLY           0x01 +#define ATTR_HIDDEN             0x02 +#define ATTR_SYSTEM             0x04 +#define ATTR_VOLUME             0x08 +#define ATTR_DIRECTORY          0x10 +#define ATTR_ARCHIVE            0x20 +#define ATTR_VSE                0x0f + +/* Name format                                                               */ +#define EXTCASE                 0x10 +#define BASECASE                0x8 + +/* Definition of the boot sector                                             */ +#define BANNER_LG               8 +#define LABEL_LG                11 + +typedef struct bootsector +{ +    unsigned char jump [3];	/* 0  Jump to boot code                      */ +    char banner [BANNER_LG];	/* 3  OEM name & version                     */ +    unsigned short secsiz;	/* 11 Bytes per sector hopefully 512         */ +    unsigned char clsiz;	/* 13 Cluster size in sectors                */ +    unsigned short nrsvsect;	/* 14 Number of reserved (boot) sectors      */ +    unsigned char nfat;		/* 16 Number of FAT tables hopefully 2       */ +    unsigned short dirents;	/* 17 Number of directory slots              */ +    unsigned short psect;	/* 19 Total sectors on disk                  */ +    unsigned char descr;	/* 21 Media descriptor=first byte of FAT     */ +    unsigned short fatlen;	/* 22 Sectors in FAT                         */ +    unsigned short nsect;	/* 24 Sectors/track                          */ +    unsigned short nheads;	/* 26 Heads                                  */ +    unsigned int nhs;	        /* 28 number of hidden sectors               */ +    unsigned int bigsect;	/* 32 big total sectors                      */ +    unsigned char physdrive;	/* 36 physical drive ?                       */ +    unsigned char reserved;	/* 37 reserved                               */ +    unsigned char dos4;		/* 38 dos > 4.0 diskette                     */ +    unsigned int serial;        /* 39 serial number                          */ +    char label [LABEL_LG];	/* 43 disk label                             */ +    char fat_type [8];		/* 54 FAT type                               */ +    unsigned char res_2m;	/* 62 reserved by 2M                         */ +    unsigned char CheckSum;	/* 63 2M checksum (not used)                 */ +    unsigned char fmt_2mf;	/* 64 2MF format version                     */ +    unsigned char wt;		/* 65 1 if write track after format          */ +    unsigned char rate_0;	/* 66 data transfer rate on track 0          */ +    unsigned char rate_any;	/* 67 data transfer rate on track<>0         */ +    unsigned short BootP;	/* 68 offset to boot program                 */ +    unsigned short Infp0;	/* 70 T1: information for track 0            */ +    unsigned short InfpX;	/* 72 T2: information for track<>0           */ +    unsigned short InfTm;	/* 74 T3: track sectors size table           */ +    unsigned short DateF;	/* 76 Format date                            */ +    unsigned short TimeF;	/* 78 Format time                            */ +    unsigned char junk [BOOTSIZE - 80];	/* 80 remaining data                 */ +} __attribute__ ((packed)) BootSector_t; + +/* Structure d'une entree de repertoire                                      */ +typedef struct directory { +    char name [8];		/* file name                                 */ +    char ext [3];		/* file extension                            */ +    unsigned char attr;		/* attribute byte                            */ +    unsigned char Case;		/* case of short filename                    */ +    unsigned char reserved [9];	/* ??                                        */ +    unsigned char time [2];	/* time stamp                                */ +    unsigned char date [2];	/* date stamp                                */ +    unsigned short start;	/* starting cluster number                   */ +    unsigned int size;	        /* size of the file                          */ +} __attribute__ ((packed))  Directory_t; + + + +#define MAX_VFAT_SUBENTRIES 20 +#define VSE_NAMELEN 13 + +#define VSE1SIZE 5 +#define VSE2SIZE 6 +#define VSE3SIZE 2 + +#define VBUFSIZE ((MAX_VFAT_SUBENTRIES * VSE_NAMELEN) + 1) + +#define MAX_VNAMELEN (255) + +#define VSE_PRESENT 0x01 +#define VSE_LAST 0x40 +#define VSE_MASK 0x1f + +/* Flag used by vfat_lookup                                                  */ +#define DO_OPEN         1 +#define ACCEPT_PLAIN    0x20 +#define ACCEPT_DIR      0x10 +#define ACCEPT_LABEL    0x08 +#define SINGLE          2 +#define MATCH_ANY       0x40 + +struct vfat_subentry { +    unsigned char id;		        /* VSE_LAST pour la fin, VSE_MASK    */ +                                        /* pour un VSE                       */ +    char text1 [VSE1SIZE * 2];          /* Caracteres encodes sur 16 bits    */ +    unsigned char attribute;	        /* 0x0f pour les VFAT                */ +    unsigned char hash1;		/* toujours 0                        */ +    unsigned char sum;		        /* Checksum du nom court             */ +    char text2 [VSE2SIZE * 2];          /* Caracteres encodes sur 16 bits    */ +    unsigned char sector_l;             /* 0 pour les VFAT                   */ +    unsigned char sector_u;		/* 0 pour les VFAT                   */ +    char text3 [VSE3SIZE * 2];          /* Caracteres encodes sur 16 bits    */ +} __attribute__ ((packed)) ; + +struct vfat_state { +    char name [VBUFSIZE]; +    int status;             /* is now a bit map of 32 bits                   */ +    int subentries; +    unsigned char sum;      /* no need to remember the sum for each          */ +                            /*   entry, it is the same anyways               */ +} __attribute__ ((packed)) ; + +/* Conversion macros                                                         */ +#define	DOS_YEAR(dir) (((dir)->date[1] >> 1) + 1980) +#define	DOS_MONTH(dir) (((((dir)->date[1]&0x1) << 3) + ((dir)->date[0] >> 5))) +#define	DOS_DAY(dir) ((dir)->date[0] & 0x1f) +#define	DOS_HOUR(dir) ((dir)->time[1] >> 3) +#define	DOS_MINUTE(dir) (((((dir)->time[1]&0x7) << 3) + ((dir)->time[0] >> 5))) +#define	DOS_SEC(dir) (((dir)->time[0] & 0x1f) * 2) + + +#endif + diff --git a/fs/fdos/fat.c b/fs/fdos/fat.c new file mode 100644 index 000000000..42df755af --- /dev/null +++ b/fs/fdos/fat.c @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#include "dos.h" +#include "fdos.h" + + +/*----------------------------------------------------------------------------- + * fat_decode --  + *----------------------------------------------------------------------------- + */ +unsigned int fat_decode (Fs_t *fs, unsigned int num) +{ +    unsigned int start = num * 3 / 2; +    unsigned char *address = fs -> fat_buf + start; +     +    if (num < 2 || start + 1 > (fs -> fat_len * SZ_STD_SECTOR)) +        return 1; +     +    if (num & 1) +        return ((address [1] & 0xff) << 4) | ((address [0] & 0xf0 ) >> 4); +    else +        return ((address [1] & 0xf) << 8) | (address [0] & 0xff ); +} +/*----------------------------------------------------------------------------- + * check_fat --  + *----------------------------------------------------------------------------- + */ +static int check_fat (Fs_t *fs) +{ +    int i, f; + +    /* Cluster verification                                                  */ +    for (i = 3 ; i < fs -> num_clus; i++){ +        f = fat_decode (fs, i); +        if (f < FAT12_LAST && f > fs -> num_clus){ +            /* Wrong cluster number detected                                 */ +            return (-1); +        } +    } +    return (0); +} +/*----------------------------------------------------------------------------- + * read_one_fat --  + *----------------------------------------------------------------------------- + */ +static int read_one_fat (BootSector_t *boot, Fs_t *fs, int nfat) +{ +    if (dev_read (fs -> fat_buf, +                  (fs -> fat_start + nfat * fs -> fat_len), +                  fs -> fat_len) < 0) { +        return (-1); +    } + +    if (fs -> fat_buf [0] || fs -> fat_buf [1] || fs -> fat_buf [2]) { +        if ((fs -> fat_buf [0] != boot -> descr && +             (fs -> fat_buf [0] != 0xf9 || boot -> descr != MEDIA_STD)) || +            fs -> fat_buf [0] < MEDIA_STD){ +            /* Unknown Media                                                 */ +            return (-1); +        } +        if (fs -> fat_buf [1] != 0xff || fs -> fat_buf [2] != 0xff){ +            /* FAT doesn't start with good values                            */ +            return (-1); +        } +    } + +    if (fs -> num_clus >= FAT12_MAX_NB) { +        /* Too much clusters                                                 */ +        return (-1); +    } + +    return check_fat (fs); +} +/*----------------------------------------------------------------------------- + * read_fat --  + *----------------------------------------------------------------------------- + */ +int read_fat (BootSector_t *boot, Fs_t *fs) +{ +    unsigned int buflen; +    int i; + +    /* Allocate Fat Buffer                                                   */ +    buflen = fs -> fat_len * SZ_STD_SECTOR; +    if (fs -> fat_buf) { +        free (fs -> fat_buf); +    } + +    if ((fs -> fat_buf = malloc (buflen)) == NULL) { +        return (-1); +    } + +    /* Try to read each Fat                                                  */ +    for (i = 0; i< fs -> nb_fat; i++){ +        if (read_one_fat (boot, fs, i) == 0) { +            /* Fat is OK                                                     */ +            fs -> num_fat = i; +            break; +        } +    } + +    if (i == fs -> nb_fat){ +        return (-1); +    } +     +    if (fs -> fat_len > (((fs -> num_clus + 2) * +                          (FAT_BITS / 4) -1 ) / 2 / +                         SZ_STD_SECTOR + 1)) { +        return (-1); +    } +    return (0); +} + + +  + +#endif diff --git a/fs/fdos/fdos.c b/fs/fdos/fdos.c new file mode 100644 index 000000000..8963f425f --- /dev/null +++ b/fs/fdos/fdos.c @@ -0,0 +1,175 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) +#include <malloc.h> +#include "dos.h" +#include "fdos.h" + + +const char *month [] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +Fs_t    fs; +File_t  file; + +/*----------------------------------------------------------------------------- + * dos_open --  + *----------------------------------------------------------------------------- + */ +int dos_open(char *name) +{ +    int lg; +    int entry; +    char *fname; +     +    /* We need to suppress the " char around the name                        */ +    if (name [0] == '"') { +        name ++; +    } +    lg = strlen (name); +    if (name [lg - 1] == '"') { +        name [lg - 1] = '\0'; +    } + +    /* Open file system                                                      */ +    if (fs_init (&fs) < 0) { +        return -1; +    } + +    /* Init the file descriptor                                              */ +    file.name = name; +    file.fs = &fs; +     +    /* find the subdirectory containing the file                             */ +    if (open_subdir (&file) < 0) { +        return (-1); +    } + +    fname = basename (name); + +    /* if we try to open root directory                                      */ +    if (*fname == '\0') { +        file.file = file.subdir; +        return (0); +    } +     +    /* find the file in the subdir                                           */ +    entry = 0; +    if (vfat_lookup (&file.subdir, +                     file.fs, +                     &file.file.dir, +                     &entry, +                     0, +                     fname, +                     ACCEPT_DIR | ACCEPT_PLAIN | SINGLE | DO_OPEN, +                     0, +                     &file.file) != 0) { +        /* File not found                                                    */ +        printf ("File not found\n"); +        return (-1); +    } + +    return 0; +} + +/*----------------------------------------------------------------------------- + * dos_read --  + *----------------------------------------------------------------------------- + */ +int dos_read (ulong addr) +{ +    int read = 0, nb; + +    /* Try to boot a directory ?                                             */ +    if (file.file.dir.attr & (ATTR_DIRECTORY | ATTR_VOLUME)) { +        printf ("Unable to boot %s !!\n", file.name); +        return (-1); +    } +    while (read < file.file.FileSize) { +        PRINTF ("read_file (%ld)\n", (file.file.FileSize - read)); +        nb = read_file (&fs, +                        &file.file, +                        (char *)addr + read, +                        read, +                        (file.file.FileSize - read)); +        PRINTF ("read_file -> %d\n", nb); +        if (nb < 0) { +            printf ("read error\n"); +            return (-1); +        } +        read += nb; +    } +    return (read); +} +/*----------------------------------------------------------------------------- + * dos_dir --  + *----------------------------------------------------------------------------- + */ +int dos_dir (void) +{ +    int entry; +    Directory_t dir; +    char *name; +     +     +    if ((file.file.dir.attr & ATTR_DIRECTORY) == 0) { +        printf ("%s: not a directory !!\n", file.name); +        return (1); +    } +    entry = 0; +    if ((name = malloc (MAX_VNAMELEN + 1)) == NULL) { +        PRINTF ("Allcation error\n"); +        return (1); +    } +     +    while (vfat_lookup (&file.file, +                        file.fs, +                        &dir, +                        &entry, +                        0, +                        NULL, +                        ACCEPT_DIR | ACCEPT_PLAIN | MATCH_ANY, +                        name, +                        NULL) == 0) { +        /* Display file info                                                 */ +        printf ("%3.3s %9d %s %02d %04d %02d:%02d:%02d %s\n", +                (dir.attr & ATTR_DIRECTORY) ? "dir" : "   ", +                __le32_to_cpu (dir.size), +                month [DOS_MONTH (&dir) - 1], +                DOS_DAY (&dir), +                DOS_YEAR (&dir), +                DOS_HOUR (&dir), +                DOS_MINUTE (&dir), +                DOS_SEC (&dir), +                name); +         +    } +    free (name); +    return (0); +} + +#endif diff --git a/fs/fdos/fdos.h b/fs/fdos/fdos.h new file mode 100644 index 000000000..18076d866 --- /dev/null +++ b/fs/fdos/fdos.h @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _FDOS_H_ +#define _FDOS_H_ + + +#undef	FDOS_DEBUG + +#ifdef	FDOS_DEBUG +#define	PRINTF(fmt,args...)	printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* Data structure describing media                                           */ +typedef struct fs +{ +    unsigned long       tot_sectors; + +    int                 cluster_size; +    int                 num_clus; +     +    int                 fat_start; +    int                 fat_len; +    int                 nb_fat; +    int                 num_fat; +     +    int                 dir_start; +    int                 dir_len; + +    unsigned char       *fat_buf; +     +} Fs_t; + +/* Data structure describing one file system slot                            */ +typedef struct slot { +    int (*map) (struct fs *fs, +                struct slot *file, +                int where, +                int *len); +    unsigned long FileSize; + +    unsigned short int FirstAbsCluNr; +    unsigned short int PreviousAbsCluNr; +    unsigned short int PreviousRelCluNr; + +    Directory_t dir; +} Slot_t; + +typedef struct file { +    char                *name; +    int                 Case; +    Fs_t                *fs; +    Slot_t              subdir; +    Slot_t              file; +} File_t; + + +/* dev.c                                                                     */ +int dev_read (void *buffer, int where, int len); +int dev_open (void); +int check_dev (BootSector_t *boot, Fs_t *fs); + +/* fat.c                                                                     */ +unsigned int fat_decode (Fs_t *fs, unsigned int num); +int read_fat (BootSector_t *boot, Fs_t *fs); + +/* vfat.c                                                                    */ +int vfat_lookup (Slot_t *dir, +                 Fs_t *fs, +                 Directory_t *dirent, +                 int *entry, +                 int *vfat_start, +                 char *filename,  +                 int flags, +                 char *outname, +                 Slot_t *file); + +/* subdir.c                                                                  */ +char *basename (char *name); +int open_subdir (File_t *desc); +int open_file (Slot_t *file, Directory_t *dir); +int read_file (Fs_t *fs, +               Slot_t *file, +               char *buf, +               int where, +               int len); +void init_subdir (void); + +/* fs.c                                                                      */ +int fs_init (Fs_t *fs); + + +#endif + diff --git a/fs/fdos/fs.c b/fs/fdos/fs.c new file mode 100644 index 000000000..68bbde0e2 --- /dev/null +++ b/fs/fdos/fs.c @@ -0,0 +1,120 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#include "dos.h" +#include "fdos.h" + + +/*----------------------------------------------------------------------------- + * fill_fs -- Read info on file system  + *----------------------------------------------------------------------------- + */ +static int fill_fs (BootSector_t *boot, Fs_t *fs) +{ +     +    fs -> fat_start = __le16_to_cpu (boot -> nrsvsect); +    fs -> fat_len = __le16_to_cpu (boot -> fatlen); +    fs -> nb_fat = boot -> nfat; +     +    fs -> dir_start = fs -> fat_start + fs -> nb_fat * fs -> fat_len; +    fs -> dir_len = __le16_to_cpu (boot -> dirents) * MDIR_SIZE / SZ_STD_SECTOR; +    fs -> cluster_size = boot -> clsiz; +    fs -> num_clus = (fs -> tot_sectors - fs -> dir_start - fs -> dir_len) / fs -> cluster_size; + +    return (0); +} + +/*----------------------------------------------------------------------------- + * fs_init --  + *----------------------------------------------------------------------------- + */ +int fs_init (Fs_t *fs) +{ +    BootSector_t *boot; + +    /* Initialize physical device                                            */ +    if (dev_open () < 0) { +        PRINTF ("Unable to initialize the fdc\n"); +        return (-1); +    } +    init_subdir (); +     +    /* Allocate space for read the boot sector                               */ +    if ((boot = (BootSector_t *)malloc (sizeof (BootSector_t))) == NULL) { +        PRINTF ("Unable to allocate space for boot sector\n"); +        return (-1); +    } +     +    /* read boot sector                                                      */ +    if (dev_read (boot, 0, 1)){ +        PRINTF ("Error during boot sector read\n"); +        free (boot); +        return (-1); +    } + +    /* we verify it'a a DOS diskette                                         */ +    if (boot -> jump [0] !=  JUMP_0_1 && boot -> jump [0] !=  JUMP_0_2) { +        PRINTF ("Not a DOS diskette\n"); +        free (boot); +        return (-1); +    } + +    if (boot -> descr < MEDIA_STD) { +        /* We handle only recent medias (type F0)                            */ +        PRINTF ("unrecognized diskette type\n"); +        free (boot); +        return (-1); +    } + +    if (check_dev (boot, fs) < 0) { +        PRINTF ("Bad diskette\n"); +        free (boot); +        return (-1); +    } +     +    if (fill_fs (boot, fs) < 0) { +        free (boot); + +        return (-1); +    } + +    /* Read FAT                                                              */ +    if (read_fat (boot, fs) < 0) { +        free (boot); +        return (-1); +    } + +    free (boot); +    return (0); +} + + + +#endif diff --git a/fs/fdos/subdir.c b/fs/fdos/subdir.c new file mode 100644 index 000000000..5911f2e88 --- /dev/null +++ b/fs/fdos/subdir.c @@ -0,0 +1,348 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#include "dos.h" +#include "fdos.h" + +static int cache_sect; +static unsigned char cache [SZ_STD_SECTOR]; + + +#define min(x,y) ((x)<(y)?(x):(y)) + +static int descend (Slot_t *parent, +             Fs_t *fs, +                    char *path); + +/*----------------------------------------------------------------------------- + * init_subdir --  + *----------------------------------------------------------------------------- + */ +void init_subdir (void) +{ +    cache_sect = -1; +} +/*----------------------------------------------------------------------------- + * basename --  + *----------------------------------------------------------------------------- + */ +char *basename (char *name) +{ +    register char *cptr; + +    if (!name || !*name) { +        return (""); +    } +     +    for (cptr= name; *cptr++; ); +    while (--cptr >= name) { +	if (*cptr == '/')    { +            return (cptr + 1); +	} +    } +    return(name); +} +/*----------------------------------------------------------------------------- + * root_map --  + *----------------------------------------------------------------------------- + */ +static int root_map (Fs_t *fs, Slot_t *file, int where, int *len) +{ +    *len = min (*len, fs -> dir_len * SZ_STD_SECTOR - where); +    if (*len < 0 ) { +        *len = 0; +        return (-1); +    } +    return fs -> dir_start * SZ_STD_SECTOR + where; +} +/*----------------------------------------------------------------------------- + * normal_map --  + *----------------------------------------------------------------------------- + */ +static int normal_map (Fs_t *fs, Slot_t *file, int where, int *len) +{ +    int offset; +    int NrClu; +    unsigned short RelCluNr; +    unsigned short CurCluNr; +    unsigned short NewCluNr; +    unsigned short AbsCluNr; +    int clus_size; + +    clus_size = fs -> cluster_size * SZ_STD_SECTOR; +    offset = where % clus_size; + +    *len = min (*len, file -> FileSize - where); + +    if (*len < 0 ) { +        *len = 0; +        return (0); +    } + +    if (file -> FirstAbsCluNr < 2){ +        *len = 0; +        return (0); +    } + +    RelCluNr = where / clus_size; +	 +    if (RelCluNr >= file -> PreviousRelCluNr){ +        CurCluNr = file -> PreviousRelCluNr; +        AbsCluNr = file -> PreviousAbsCluNr; +    } else { +        CurCluNr = 0; +        AbsCluNr = file -> FirstAbsCluNr; +    } + + +    NrClu = (offset + *len - 1) / clus_size; +    while (CurCluNr <= RelCluNr + NrClu) { +        if (CurCluNr == RelCluNr){ +            /* we have reached the beginning of our zone. Save +             * coordinates */ +            file -> PreviousRelCluNr = RelCluNr; +            file -> PreviousAbsCluNr = AbsCluNr; +        } +        NewCluNr = fat_decode (fs, AbsCluNr); +        if (NewCluNr == 1 || NewCluNr == 0) { +            PRINTF("Fat problem while decoding %d %x\n",  +                    AbsCluNr, NewCluNr); +            return (-1); +        } +        if (CurCluNr == RelCluNr + NrClu) { +            break; +        } + +        if (CurCluNr < RelCluNr && NewCluNr == FAT12_END) { +            *len = 0; +            return 0; +        } + +        if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1) +            break; +        CurCluNr++; +        AbsCluNr = NewCluNr; +    } + +    *len = min (*len, (1 + CurCluNr - RelCluNr) * clus_size - offset); + +    return (((file -> PreviousAbsCluNr - 2) * fs -> cluster_size + +             fs -> dir_start + fs -> dir_len) * +            SZ_STD_SECTOR + offset); +} +/*----------------------------------------------------------------------------- + * open_subdir -- open the subdir containing the file + *----------------------------------------------------------------------------- + */ +int open_subdir (File_t *desc) +{ +    char *pathname; +    char *tmp, *s, *path; +    char terminator; +     +    if ((pathname = (char *)malloc (MAX_PATH)) == NULL) { +        return (-1); +    } +     +    strcpy (pathname, desc -> name); +     +    /* Suppress file name                                                    */ +    tmp = basename (pathname); +    *tmp = '\0'; + +    /* root directory  init                                                  */ +    desc -> subdir.FirstAbsCluNr = 0; +    desc -> subdir.FileSize = -1; +    desc -> subdir.map = root_map; +    desc -> subdir.dir.attr = ATTR_DIRECTORY; +     +    tmp = pathname; +    for (s = tmp; ; ++s) { +        if (*s == '/' || *s == '\0') { +            path = tmp; +            terminator = *s; +            *s = '\0'; +            if (s != tmp && strcmp (path,".")) { +                if (descend (&desc -> subdir, desc -> fs, path) < 0) { +                    free (pathname); +                    return (-1); +                } +            } +            if (terminator == 0) { +                break; +            } +            tmp = s + 1; +        } +    } +    free (pathname); +    return (0); +} +/*----------------------------------------------------------------------------- + * descend --  + *----------------------------------------------------------------------------- + */ +static int descend (Slot_t *parent, +             Fs_t *fs, +             char *path) +{ +    int entry; +    Slot_t SubDir; + +    if(path[0] == '\0' || strcmp (path, ".") == 0) { +        return (0); +    } +     + +    entry = 0; +    if (vfat_lookup (parent, +                     fs, +                     &(SubDir.dir), +                     &entry, +                     0, +                     path, +                     ACCEPT_DIR | SINGLE | DO_OPEN, +                     0, +                     &SubDir) == 0) { +        *parent = SubDir; +        return (0); +    } + +    if (strcmp(path, "..") == 0) { +        parent -> FileSize = -1; +        parent -> FirstAbsCluNr = 0; +        parent -> map = root_map; +        return (0); +    } +    return (-1); +} +/*----------------------------------------------------------------------------- + * open_file --  + *----------------------------------------------------------------------------- + */ +int open_file (Slot_t *file, Directory_t *dir) +{ +    int first; +    unsigned long size; + +    first = __le16_to_cpu (dir -> start); + +    if(first == 0 && +       (dir -> attr & ATTR_DIRECTORY) != 0) { +        file -> FirstAbsCluNr = 0; +        file -> FileSize = -1; +        file -> map = root_map; +        return (0); +    } +	 +    if ((dir -> attr & ATTR_DIRECTORY) != 0) { +        size = (1UL << 31) - 1; +    } +    else { +        size = __le32_to_cpu (dir -> size); +    } + +    file -> map = normal_map; +    file -> FirstAbsCluNr = first; +    file -> PreviousRelCluNr = 0xffff; +    file -> FileSize = size; +    return (0); +} +/*----------------------------------------------------------------------------- + * read_file --  + *----------------------------------------------------------------------------- + */ +int read_file (Fs_t *fs, +               Slot_t *file, +               char *buf, +               int where, +               int len) +{ +    int pos; +    int read, nb, sect, offset; +     +    pos = file -> map (fs, file, where, &len); +    if  (pos < 0) { +        return -1; +    } +    if (len == 0) { +        return (0); +    } + +    /* Compute sector number                                                 */ +    sect = pos / SZ_STD_SECTOR; +    offset = pos % SZ_STD_SECTOR; +    read = 0; +     +    if (offset) { +        /* Read doesn't start at the sector beginning. We need to use our    */ +        /* cache                                                             */ +        if (sect != cache_sect) { +            if (dev_read (cache, sect, 1) < 0) { +                return (-1); +            } +            cache_sect = sect; +        } +        nb = min (len, SZ_STD_SECTOR - offset); +         +        memcpy (buf, cache + offset, nb); +        read += nb; +        len -= nb; +        sect += 1; +    } + +    if (len > SZ_STD_SECTOR) { +        nb = (len - 1) / SZ_STD_SECTOR; +        if (dev_read (buf + read, sect, nb) < 0) { +            return ((read) ? read : -1); +        } +        /* update sector position                                            */ +        sect += nb; + +        /* Update byte position                                              */ +        nb *= SZ_STD_SECTOR; +        read += nb; +        len -= nb; +    } + +    if (len) { +        if (sect != cache_sect) { +            if (dev_read (cache, sect, 1) < 0) { +                return ((read) ? read : -1); +                cache_sect = -1; +            } +            cache_sect = sect; +        } +         +        memcpy (buf + read, cache, len); +        read += len; +    } +    return (read); +} +#endif diff --git a/fs/fdos/vfat.c b/fs/fdos/vfat.c new file mode 100644 index 000000000..f8287952e --- /dev/null +++ b/fs/fdos/vfat.c @@ -0,0 +1,357 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) +#include <linux/ctype.h> + +#include "dos.h" +#include "fdos.h" + +static int dir_read (Fs_t *fs, +                     Slot_t *dir, +                     Directory_t *dirent, +                     int num, +                     struct vfat_state *v); + +static int unicode_read (char *in, char *out, int num); +static int match (const char *s, const char *p); +static unsigned char sum_shortname (char *name); +static int check_vfat (struct vfat_state *v, Directory_t *dir); +static char *conv_name (char *name, char *ext, char Case, char *ans); + + +/*----------------------------------------------------------------------------- + * clear_vfat --  + *----------------------------------------------------------------------------- + */ +static void clear_vfat (struct vfat_state *v) +{ +    v -> subentries = 0; +    v -> status = 0; +} + +/*----------------------------------------------------------------------------- + * vfat_lookup --  + *----------------------------------------------------------------------------- + */ +int vfat_lookup (Slot_t *dir, +                 Fs_t *fs, +                 Directory_t *dirent, +                 int *entry, +                 int *vfat_start, +                 char *filename,  +                 int flags, +                 char *outname, +                 Slot_t *file) +{ +    int found; +    struct vfat_state vfat; +    char newfile [VSE_NAMELEN]; +    int vfat_present = 0; + +    if (*entry == -1) { +        return -1; +    } + +    found = 0; +    clear_vfat (&vfat); +    while (1) { +        if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) { +            if (vfat_start) { +                *vfat_start = *entry; +            } +            break; +        } +        (*entry)++; + +        /* Empty slot                                                        */ +        if (dirent -> name[0] == '\0'){ +            if (vfat_start == 0) { +                break; +            } +            continue; +        } + +        if (dirent -> attr == ATTR_VSE) { +            /* VSE entry, continue                                           */ +            continue; +        } +        if ( (dirent -> name [0] == DELMARK) || +             ((dirent -> attr & ATTR_DIRECTORY) != 0 && +              (flags & ACCEPT_DIR) == 0) || +             ((dirent -> attr & ATTR_VOLUME) != 0 && +              (flags & ACCEPT_LABEL) == 0) || +             (((dirent -> attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0) && +              (flags & ACCEPT_PLAIN) == 0)) { +            clear_vfat (&vfat); +            continue; +        } + +        vfat_present = check_vfat (&vfat, dirent); +        if (vfat_start) { +            *vfat_start = *entry - 1; +            if (vfat_present) { +                *vfat_start -= vfat.subentries; +            } +        } + +        if (dirent -> attr & ATTR_VOLUME) { +            strncpy (newfile, dirent -> name, 8); +            newfile [8] = '\0'; +            strncat (newfile, dirent -> ext, 3); +            newfile [11] = '\0'; +        } +        else { +            conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile); +        } + +        if (flags & MATCH_ANY) { +            found = 1; +            break; +        } + +        if ((vfat_present && match (vfat.name, filename)) || +            (match (newfile, filename))) { +            found = 1; +            break; +        } +        clear_vfat (&vfat); +    } + +    if (found) { +        if ((flags & DO_OPEN) && file) { +            if (open_file (file, dirent) < 0) { +                return (-1); +            } +        } +        if (outname) { +            if (vfat_present) { +                strcpy (outname, vfat.name); +            } +            else { +                strcpy (outname, newfile); +            } +        } +        return (0);                    /* File found                         */ +    } else { +        *entry = -1; +        return -1;                      /* File not found                    */ +    } +} + +/*----------------------------------------------------------------------------- + * dir_read -- Read one directory entry + *----------------------------------------------------------------------------- + */ +static int dir_read (Fs_t *fs, +              Slot_t *dir, +              Directory_t *dirent, +              int num, +              struct vfat_state *v) +{ + +    /* read the directory entry                                              */ +    if (read_file (fs, +                   dir, +                   (char *)dirent, +                   num * MDIR_SIZE, +                   MDIR_SIZE) != MDIR_SIZE) { +        return (-1); +    } + +    if (v && (dirent -> attr == ATTR_VSE)) { +        struct vfat_subentry *vse; +        unsigned char id, last_flag; +        char *c; + +        vse = (struct vfat_subentry *) dirent; +        id = vse -> id & VSE_MASK; +        last_flag = (vse -> id & VSE_LAST); +        if (id > MAX_VFAT_SUBENTRIES) { +            /* Invalid VSE entry                                             */ +            return (-1); +        } + + +        /* Decode VSE                                                        */ +        if(v -> sum != vse -> sum) { +            clear_vfat (v); +            v -> sum = vse -> sum; +        } + +         +        v -> status |= 1 << (id - 1); +        if (last_flag) { +            v -> subentries = id; +        } + +        c = &(v -> name [VSE_NAMELEN * (id - 1)]); +        c += unicode_read (vse->text1, c, VSE1SIZE); +        c += unicode_read (vse->text2, c, VSE2SIZE); +        c += unicode_read (vse->text3, c, VSE3SIZE); +		 +        if (last_flag) { +            *c = '\0';	        /* Null terminate long name                  */ +        } +         +    } +    return (0); +} + +/*----------------------------------------------------------------------------- + * unicode_read --  + *----------------------------------------------------------------------------- + */ +static int unicode_read (char *in, char *out, int num) +{ +    int j; +     +    for (j = 0; j < num; ++j) { +        if (in [1]) +            *out = '_'; +        else +            *out = in [0]; +        out ++; +        in += 2; +    } +    return num; +} + +/*----------------------------------------------------------------------------- + * match --  + *----------------------------------------------------------------------------- + */ +static int match (const char *s, const char *p) +{ + +    for (; *p != '\0'; ) { +        if (toupper (*s) != toupper (*p)) { +            return (0); +        } +        p++; +        s++; +    } +     +    if (*s != '\0') { +        return (0); +    } +    else { +        return (1); +    } +} +/*----------------------------------------------------------------------------- + * sum_shortname --  + *----------------------------------------------------------------------------- + */ +static unsigned char sum_shortname (char *name) +{ +    unsigned char sum; +    int j; +     +    for (j = sum = 0; j < 11; ++j) { +        sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + +            (name [j] ? name [j] : ' '); +    } +    return (sum); +} +/*----------------------------------------------------------------------------- + * check_vfat --  + * Return 1 if long name is valid, 0 else + *----------------------------------------------------------------------------- + */ +static int check_vfat (struct vfat_state *v, Directory_t *dir) +{ +    char name[12]; +     +    if (v -> subentries == 0) { +        return 0; +    } +     +    strncpy (name, dir -> name, 8); +    strncpy (name + 8, dir -> ext, 3); +    name [11] = '\0'; +     +    if (v -> sum != sum_shortname (name)) { +        return 0; +    } +     +    if( (v -> status & ((1 << v -> subentries) - 1)) != +        (1 << v -> subentries) - 1) { +        return 0; +    } +    v->name [VSE_NAMELEN * v -> subentries] = 0; +     +    return 1; +} +/*----------------------------------------------------------------------------- + * conv_name --  + *----------------------------------------------------------------------------- + */ +static char *conv_name (char *name, char *ext, char Case, char *ans) +{ +    char tname [9], text [4]; +    int i; + +    i = 0; +    while (i < 8 && name [i] != ' ' && name [i] != '\0') { +        tname [i] = name [i]; +        i++; +    } +    tname [i] = '\0'; +     +    if (Case & BASECASE) { +        for (i = 0; i < 8 && tname [i]; i++) { +            tname [i] = tolower (tname [i]); +        } +    } + +    i = 0; +    while (i < 3 && ext [i] != ' ' && ext [i] != '\0') { +        text [i] = ext [i]; +        i++; +    } +    text [i] = '\0'; + +    if (Case & EXTCASE){ +        for (i = 0; i < 3 && text [i]; i++) { +            text [i] = tolower (text [i]); +        } +    } + +    if (*text) { +        strcpy (ans, tname); +        strcat (ans, "."); +        strcat (ans, text); +    } +    else { +        strcpy(ans, tname); +    } +    return (ans); +} + + +#endif diff --git a/i386_config.mk b/i386_config.mk new file mode 100644 index 000000000..9e6d37d0e --- /dev/null +++ b/i386_config.mk @@ -0,0 +1,24 @@ +# +# (C) Copyright 2000-2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_CPPFLAGS += -DCONFIG_I386 -D__I386__ diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h new file mode 100644 index 000000000..a3063cacc --- /dev/null +++ b/include/asm-i386/bitops.h @@ -0,0 +1,384 @@ +#ifndef _I386_BITOPS_H +#define _I386_BITOPS_H + +/* + * Copyright 1992, Linus Torvalds. + */ + +#include <linux/config.h> + +/* + * These have to be done with inline assembly: that way the bit-setting + * is guaranteed to be atomic. All bit operations return 0 if the bit + * was cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ + +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + +#define ADDR (*(volatile long *) addr) + +/** + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered.  See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void set_bit(int nr, volatile void * addr) +{ +	__asm__ __volatile__( LOCK_PREFIX +		"btsl %1,%0" +		:"=m" (ADDR) +		:"Ir" (nr)); +} + +/** + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static __inline__ void __set_bit(int nr, volatile void * addr) +{ +	__asm__( +		"btsl %1,%0" +		:"=m" (ADDR) +		:"Ir" (nr)); +} + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered.  However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static __inline__ void clear_bit(int nr, volatile void * addr) +{ +	__asm__ __volatile__( LOCK_PREFIX +		"btrl %1,%0" +		:"=m" (ADDR) +		:"Ir" (nr)); +} +#define smp_mb__before_clear_bit()	barrier() +#define smp_mb__after_clear_bit()	barrier() + +/** + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static __inline__ void __change_bit(int nr, volatile void * addr) +{ +	__asm__ __volatile__( +		"btcl %1,%0" +		:"=m" (ADDR) +		:"Ir" (nr)); +} + +/** + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void change_bit(int nr, volatile void * addr) +{ +	__asm__ __volatile__( LOCK_PREFIX +		"btcl %1,%0" +		:"=m" (ADDR) +		:"Ir" (nr)); +} + +/** + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +static __inline__ int test_and_set_bit(int nr, volatile void * addr) +{ +	int oldbit; + +	__asm__ __volatile__( LOCK_PREFIX +		"btsl %2,%1\n\tsbbl %0,%0" +		:"=r" (oldbit),"=m" (ADDR) +		:"Ir" (nr) : "memory"); +	return oldbit; +} + +/** + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +static __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ +	int oldbit; + +	__asm__( +		"btsl %2,%1\n\tsbbl %0,%0" +		:"=r" (oldbit),"=m" (ADDR) +		:"Ir" (nr)); +	return oldbit; +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +static __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ +	int oldbit; + +	__asm__ __volatile__( LOCK_PREFIX +		"btrl %2,%1\n\tsbbl %0,%0" +		:"=r" (oldbit),"=m" (ADDR) +		:"Ir" (nr) : "memory"); +	return oldbit; +} + +/** + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered.   + * If two examples of this operation race, one can appear to succeed + * but actually fail.  You must protect multiple accesses with a lock. + */ +static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ +	int oldbit; + +	__asm__( +		"btrl %2,%1\n\tsbbl %0,%0" +		:"=r" (oldbit),"=m" (ADDR) +		:"Ir" (nr)); +	return oldbit; +} + +/* WARNING: non atomic and it can be reordered! */ +static __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ +	int oldbit; + +	__asm__ __volatile__( +		"btcl %2,%1\n\tsbbl %0,%0" +		:"=r" (oldbit),"=m" (ADDR) +		:"Ir" (nr) : "memory"); +	return oldbit; +} + +/** + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered.   + * It also implies a memory barrier. + */ +static __inline__ int test_and_change_bit(int nr, volatile void * addr) +{ +	int oldbit; + +	__asm__ __volatile__( LOCK_PREFIX +		"btcl %2,%1\n\tsbbl %0,%0" +		:"=r" (oldbit),"=m" (ADDR) +		:"Ir" (nr) : "memory"); +	return oldbit; +} + +#if 0 /* Fool kernel-doc since it doesn't do macros yet */ +/** + * test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + */ +static int test_bit(int nr, const volatile void * addr); +#endif + +static __inline__ int constant_test_bit(int nr, const volatile void * addr) +{ +	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; +} + +static __inline__ int variable_test_bit(int nr, volatile void * addr) +{ +	int oldbit; + +	__asm__ __volatile__( +		"btl %2,%1\n\tsbbl %0,%0" +		:"=r" (oldbit) +		:"m" (ADDR),"Ir" (nr)); +	return oldbit; +} + +#define test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + constant_test_bit((nr),(addr)) : \ + variable_test_bit((nr),(addr))) + +/** + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +static __inline__ int find_first_zero_bit(void * addr, unsigned size) +{ +	int d0, d1, d2; +	int res; + +	if (!size) +		return 0; +	/* This looks at memory. Mark it volatile to tell gcc not to move it around */ +	__asm__ __volatile__( +		"movl $-1,%%eax\n\t" +		"xorl %%edx,%%edx\n\t" +		"repe; scasl\n\t" +		"je 1f\n\t" +		"xorl -4(%%edi),%%eax\n\t" +		"subl $4,%%edi\n\t" +		"bsfl %%eax,%%edx\n" +		"1:\tsubl %%ebx,%%edi\n\t" +		"shll $3,%%edi\n\t" +		"addl %%edi,%%edx" +		:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) +		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr)); +	return res; +} + +/** + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +static __inline__ int find_next_zero_bit (void * addr, int size, int offset) +{ +	unsigned long * p = ((unsigned long *) addr) + (offset >> 5); +	int set = 0, bit = offset & 31, res; +	 +	if (bit) { +		/* +		 * Look for zero in first byte +		 */ +		__asm__("bsfl %1,%0\n\t" +			"jne 1f\n\t" +			"movl $32, %0\n" +			"1:" +			: "=r" (set) +			: "r" (~(*p >> bit))); +		if (set < (32 - bit)) +			return set + offset; +		set = 32 - bit; +		p++; +	} +	/* +	 * No zero yet, search remaining full bytes for a zero +	 */ +	res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); +	return (offset + set + res); +} + +/** + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +static __inline__ unsigned long ffz(unsigned long word) +{ +	__asm__("bsfl %1,%0" +		:"=r" (word) +		:"r" (~word)); +	return word; +} + +#ifdef __KERNEL__ + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static __inline__ int ffs(int x) +{ +	int r; + +	__asm__("bsfl %1,%0\n\t" +		"jnz 1f\n\t" +		"movl $-1,%0\n" +		"1:" : "=r" (r) : "g" (x)); +	return r+1; +} + +/** + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#endif /* __KERNEL__ */ + +#ifdef __KERNEL__ + +#define ext2_set_bit                 __test_and_set_bit +#define ext2_clear_bit               __test_and_clear_bit +#define ext2_test_bit                test_bit +#define ext2_find_first_zero_bit     find_first_zero_bit +#define ext2_find_next_zero_bit      find_next_zero_bit + +/* Bitmap functions for the minix filesystem.  */ +#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr) +#define minix_set_bit(nr,addr) __set_bit(nr,addr) +#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* __KERNEL__ */ + +#endif /* _I386_BITOPS_H */ diff --git a/include/asm-i386/byteorder.h b/include/asm-i386/byteorder.h new file mode 100644 index 000000000..bbfb629fa --- /dev/null +++ b/include/asm-i386/byteorder.h @@ -0,0 +1,47 @@ +#ifndef _I386_BYTEORDER_H +#define _I386_BYTEORDER_H + +#include <asm/types.h> + +#ifdef __GNUC__ + +/* For avoiding bswap on i386 */ +#ifdef __KERNEL__ +#include <linux/config.h> +#endif + +static __inline__ __const__ __u32 ___arch__swab32(__u32 x) +{ +#ifdef CONFIG_X86_BSWAP +	__asm__("bswap %0" : "=r" (x) : "0" (x)); +#else +	__asm__("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/ +		"rorl $16,%0\n\t"	/* swap words		*/ +		"xchgb %b0,%h0"		/* swap higher bytes	*/ +		:"=q" (x) +		: "0" (x)); +#endif +	return x; +} + +static __inline__ __const__ __u16 ___arch__swab16(__u16 x) +{ +	__asm__("xchgb %b0,%h0"		/* swap bytes		*/ \ +		: "=q" (x) \ +		:  "0" (x)); \ +		return x; +} + +#define __arch__swab32(x) ___arch__swab32(x) +#define __arch__swab16(x) ___arch__swab16(x) + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +#  define __BYTEORDER_HAS_U64__ +#  define __SWAB_64_THRU_32__ +#endif + +#endif /* __GNUC__ */ + +#include <linux/byteorder/little_endian.h> + +#endif /* _I386_BYTEORDER_H */ diff --git a/include/asm-i386/global_data.h b/include/asm-i386/global_data.h new file mode 100644 index 000000000..324b4357f --- /dev/null +++ b/include/asm-i386/global_data.h @@ -0,0 +1,60 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef	__ASM_GBL_DATA_H +#define __ASM_GBL_DATA_H +/* + * The following data structure is placed in some memory wich is + * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or + * some locked parts of the data cache) to allow for a minimum set of + * global variables during system initialization (until we have set + * up the memory controller so that we can use RAM). + * + * Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t) + */ + +typedef	struct { +	bd_t		*bd; +	unsigned long	flags; +	unsigned long	baudrate; +	unsigned long	have_console;	/* serial_init() was called */ +	unsigned long	reloc_off;	/* Relocation Offset */ +	unsigned long	env_addr;	/* Address  of Environment struct */ +	unsigned long	env_valid;	/* Checksum of Environment valid? */ +	unsigned long	cpu_clk;	/* CPU clock in Hz!		*/ +	unsigned long	bus_clk; +	unsigned long	ram_size;	/* RAM size */ +	unsigned long	reset_status;	/* reset status register at boot */ +} gd_t; + +/* + * Global Data Flags + */ +#define	GD_FLG_RELOC	0x00001		/* Code was relocated to RAM		*/ +#define	GD_FLG_DEVINIT	0x00002		/* Devices have been initialized	*/ + +extern gd_t *global_data; + +#define DECLARE_GLOBAL_DATA_PTR     gd_t *gd = global_data + +#endif /* __ASM_GBL_DATA_H */ diff --git a/include/asm-i386/i8254.h b/include/asm-i386/i8254.h new file mode 100644 index 000000000..e13f04e58 --- /dev/null +++ b/include/asm-i386/i8254.h @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +/* i8254.h Intel 8254 PIT registers */ + + +#ifndef _ASMI386_I8254_H_ +#define _ASMI386_I8954_H_       1 + + + +#define PIT_T0		0x00		/* PIT channel 0 count/status */ +#define PIT_T1		0x01		/* PIT channel 1 count/status */ +#define PIT_T2		0x02		/* PIT channel 2 count/status */ +#define PIT_COMMAND	0x03		/* PIT mode control, latch and read back */ + +/* PIT Command Register Bit Definitions */ + +#define PIT_CMD_CTR0	0x00		/* Select PIT counter 0 */ +#define PIT_CMD_CTR1	0x40		/* Select PIT counter 1 */ +#define PIT_CMD_CTR2	0x80		/* Select PIT counter 2 */ + +#define PIT_CMD_LATCH	0x00		/* Counter Latch Command */ +#define PIT_CMD_LOW	0x10		/* Access counter bits 7-0 */ +#define PIT_CMD_HIGH	0x20		/* Access counter bits 15-8 */ +#define PIT_CMD_BOTH	0x30		/* Access counter bits 15-0 in two accesses */ + +#define PIT_CMD_MODE0	0x00		/* Select mode 0 */ +#define PIT_CMD_MODE1	0x02		/* Select mode 1 */ +#define PIT_CMD_MODE2	0x04		/* Select mode 2 */ +#define PIT_CMD_MODE3	0x06		/* Select mode 3 */ +#define PIT_CMD_MODE4	0x08		/* Select mode 4 */ +#define PIT_CMD_MODE5	0x0A		/* Select mode 5 */ + +#endif diff --git a/include/asm-i386/i8259.h b/include/asm-i386/i8259.h new file mode 100644 index 000000000..0419e0e26 --- /dev/null +++ b/include/asm-i386/i8259.h @@ -0,0 +1,88 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* i8259.h i8259 PIC Registers */ + +#ifndef _ASMI386_I8259_H_ +#define _ASMI386_I8959_H_       1 + + +/* PIC I/O mapped registers */ + +#define IRR		0x0	/* Interrupt Request Register */ +#define ISR		0x0	/* In-Service Register */ +#define ICW1		0x0	/* Initialization Control Word 1 */ +#define OCW2		0x0	/* Operation Control Word 2 */ +#define OCW3		0x0	/* Operation Control Word 3 */ +#define ICW2		0x1	/* Initialization Control Word 2 */ +#define ICW3		0x1	/* Initialization Control Word 3 */ +#define ICW4		0x1	/* Initialization Control Word 4 */ +#define IMR		0x1	/* Interrupt Mask Register */ + +/* bits for IRR, IMR, ISR and ICW3 */ +#define	IR7		0x80	/* IR7 */ +#define	IR6		0x40	/* IR6 */ +#define	IR5		0x20	/* IR5 */ +#define	IR4		0x10	/* IR4 */ +#define	IR3		0x08	/* IR3 */ +#define	IR2		0x04	/* IR2 */ +#define	IR1		0x02	/* IR1 */ +#define	IR0		0x01	/* IR0 */ + +/* bits for SEOI */ +#define	SEOI_IR7	0x07	/* IR7 */ +#define	SEOI_IR6	0x06	/* IR6 */ +#define	SEOI_IR5	0x05	/* IR5 */ +#define	SEOI_IR4	0x04	/* IR4 */ +#define	SEOI_IR3	0x03	/* IR3 */ +#define	SEOI_IR2	0x02	/* IR2 */ +#define	SEOI_IR1	0x01	/* IR1 */ +#define	SEOI_IR0	0x00	/* IR0 */ + +/* OCW2 bits */ +#define OCW2_RCLR	0x00	/* Rotate/clear */ +#define OCW2_NEOI	0x20	/* Non specific EOI */ +#define OCW2_NOP	0x40	/* NOP */ +#define OCW2_SEOI	0x60	/* Specific EOI */ +#define OCW2_RSET	0x80	/* Rotate/set */ +#define OCW2_REOI	0xA0	/* Rotate on non specific EOI */ +#define OCW2_PSET	0xC0	/* Priority Set Command */ +#define OCW2_RSEOI	0xE0	/* Rotate on specific EOI */ + +/* ICW1 bits */ +#define ICW1_SEL	0x10	/* Select ICW1 */ +#define ICW1_LTIM	0x08	/* Level-Triggered Interrupt Mode */ +#define ICW1_ADI	0x04	/* Address Interval */ +#define ICW1_SNGL	0x02	/* Single PIC */ +#define ICW1_EICW4	0x01	/* Expect initilization ICW4 */ + +/* ICW2 is the starting vector number */ + +/* ICW2 is bit-mask of present slaves for a master device,  + * or the slave ID for a slave device */ + +/* ICW4 bits */ +#define	ICW4_AEOI	0x02	/* Automatic EOI Mode */ +#define ICW4_PM		0x01	/* Microprocessor Mode */ + +#endif diff --git a/include/asm-i386/ibmpc.h b/include/asm-i386/ibmpc.h new file mode 100644 index 000000000..abdd1d762 --- /dev/null +++ b/include/asm-i386/ibmpc.h @@ -0,0 +1,47 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_IBMPC_H_ +#define __ASM_IBMPC_H_ 1 + +/* misc ports in an ibm compatible pc */ + +#define MASTER_PIC      0x20 +#define PIT_BASE	0x40 +#define KBDDATA         0x60 +#define SYSCTLB         0x62 +#define KBDCMD          0x64 +#define SYSCTLA         0x92 +#define SLAVE_PIC       0xa0 + +#if 1 +#define UART0_BASE     0x3f8 +#define UART1_BASE     0x2f8 +#else +/* FixMe: uarts swapped */ +#define UART0_BASE     0x2f8 +#define UART1_BASE     0x3f8 +#endif + + +#endif diff --git a/include/asm-i386/ic/ali512x.h b/include/asm-i386/ic/ali512x.h new file mode 100644 index 000000000..5bc1bd790 --- /dev/null +++ b/include/asm-i386/ic/ali512x.h @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_IC_ALI512X_H_ +#define __ASM_IC_ALI512X_H_ + +# define ALI_INDEX    0x3f0 +# define ALI_DATA     0x3f1 + +# define ALI_ENABLED  1 +# define ALI_DISABLED 0 + +# define ALI_UART1    0 +# define ALI_UART2    1 + +/* setup functions */ +void ali512x_init(void); +void ali512x_set_fdc(int enabled, u16 io, u8 irq, u8 dma_channel); +void ali512x_set_pp(int enabled, u16 io, u8 irq, u8 dma_channel); +void ali512x_set_uart(int enabled, int index, u16 io, u8 irq); +void ali512x_set_rtc(int enabled, u16 io, u8 irq); +void ali512x_set_kbc(int enabled, u8 kbc_irq, u8 mouse_irq); +void ali512x_set_cio(int enabled); + + +/* common I/O functions */ +void ali512x_cio_function(int pin, int special, int inv, int input); +void ali512x_cio_out(int pin, int value); +int ali512x_cio_in(int pin); + +/* misc features */ +void ali512x_set_uart2_irda(int enabled); + +#endif diff --git a/include/asm-i386/ic/sc520.h b/include/asm-i386/ic/sc520.h new file mode 100644 index 000000000..9708504e3 --- /dev/null +++ b/include/asm-i386/ic/sc520.h @@ -0,0 +1,249 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ASM_IC_SC520_H_ +#define _ASM_IC_SC520_H_ 1 + +/* Memory mapped configuration registers, MMCR */ +#define SC520_REVID		0x0000		/* ElanSC520 Microcontroller Revision ID Register */ +#define SC520_CPUCTL		0x0002		/* Am5x86 CPU Control Register */ +#define SC520_DRCCTL            0x0010          /* SDRAM Control Register */ +#define SC520_DRCTMCTL		0x0012		/* SDRAM Timing Control Register */ +#define SC520_DRCCFG		0x0014		/* SDRAM Bank Configuration Register*/ +#define SC520_DRCBENDADR	0x0018		/* SDRAM Bank 0-3 Ending Address Register*/ +#define SC520_ECCCTL		0x0020		/* ECC Control Register */ +#define SC520_ECCSTA		0x0021		/* ECC Status Register */ +#define SC520_ECCCKBPOS		0x0022		/* ECC Check Bit Position Register */ +#define SC520_ECCSBADD		0x0024		/* ECC Single-Bit Error Address Register */ +#define SC520_DBCTL		0x0040		/* SDRAM Buffer Control Register */ +#define SC520_BOOTCSCTL		0x0050		/* /BOOTCS Control Register */ +#define SC520_ROMCS1CTL		0x0054		/* /ROMCS1 Control Register */ +#define SC520_ROMCS2CTL		0x0056		/* /ROMCS2 Control Register */ +#define SC520_HBCTL		0x0060 		/* Host Bridge Control Register */ +#define SC520_HBTGTIRQCTL	0x0062		/* Host Bridge Target Interrupt Control Register */ +#define SC520_HBTGTIRQSTA	0x0064		/* Host Bridge Target Interrupt Status Register */ +#define SC520_HBMSTIRQCTL	0x0066		/* Host Bridge Target Interrupt Control Register */ +#define SC520_HBMSTIRQSTA	0x0068		/* Host Bridge Master Interrupt Status Register */ +#define SC520_MSTINTADD		0x006c		/* Host Bridge Master Interrupt Address Register */ +#define SC520_SYSARBCTL		0x0070		/* System Arbiter Control Register */ +#define SC520_PCIARBSTA		0x0071		/* PCI Bus Arbiter Status Register */ +#define SC520_SYSARBMENB	0x0072		/* System Arbiter Master Enable Register */ +#define SC520_ARBPRICTL		0x0074		/* Arbiter Priority Control Register */ +#define SC520_ADDDECCTL     	0x0080 		/* Address Decode Control Register */ +#define SC520_WPVSTA        	0x0082		/* Write-Protect Violation Status Register */ +#define SC520_PAR0          	0x0088		/* Programmable Address Region 0 Register */ +#define SC520_PAR1          	0x008c       	/* Programmable Address Region 1 Register */ +#define SC520_PAR2          	0x0090       	/* Programmable Address Region 2 Register */ +#define SC520_PAR3          	0x0094      	/* Programmable Address Region 3 Register */ +#define SC520_PAR4          	0x0098       	/* Programmable Address Region 4 Register */ +#define SC520_PAR5          	0x009c       	/* Programmable Address Region 5 Register */ +#define SC520_PAR6         	0x00a0      	/* Programmable Address Region 6 Register */ +#define SC520_PAR7          	0x00a4       	/* Programmable Address Region 7 Register */ +#define SC520_PAR8          	0x00a8       	/* Programmable Address Region 8 Register */ +#define SC520_PAR9          	0x00ac       	/* Programmable Address Region 9 Register */ +#define SC520_PAR10         	0x00b0       	/* Programmable Address Region 10 Register */ +#define SC520_PAR11         	0x00b4       	/* Programmable Address Region 11 Register */ +#define SC520_PAR12         	0x00b8       	/* Programmable Address Region 12 Register */ +#define SC520_PAR13         	0x00bc       	/* Programmable Address Region 13 Register */ +#define SC520_PAR14         	0x00c0       	/* Programmable Address Region 14 Register */ +#define SC520_PAR15		0x00c4		/* Programmable Address Region 15 Register */ +#define SC520_GPECHO		0x0c00		/* GP Echo Mode Register */ +#define SC520_GPCSDW		0x0c01		/* GP Chip Select Data Width Register */ +#define SC520_GPCSQUAL		0x0c02		/* GP Chip Select Qualification Register */ +#define SC520_GPCSRT		0x0c08		/* GP Chip Select Recovery Time Register */ +#define SC520_GPCSPW		0x0c09		/* GP Chip Select Pulse Width Register */ +#define SC520_GPCSOFF		0x0c0a		/* GP Chip Select Offset Register */ +#define SC520_GPRDW		0x0c0b		/* GP Read Pulse Width Register */ +#define SC520_GPRDOFF		0x0c0c		/* GP Read Offset Register */ +#define SC520_GPWRW		0x0c0d		/* GP Write Pulse Width Register */ +#define SC520_GPWROFF		0x0c0e		/* GP Write Offset Register */ +#define SC520_GPALEW		0x0c0f		/* GP ALE Pulse Width Register */ +#define SC520_GPALEOFF		0x0c10		/* GP ALE Offset Register */ +#define SC520_PIOPFS15_0	0x0c20		/* PIO15-PIO0 Pin Function Select */ +#define SC520_PIOPFS31_16	0x0c22		/* PIO31-PIO16 Pin Function Select */ +#define SC520_CSPFS		0x0c24		/* Chip Select Pin Function Select */ +#define SC520_CLKSEL		0x0c26		/* Clock Select */ +#define SC520_DSCTL		0x0c28		/* Drive Strength Control */ +#define SC520_PIODIR15_0	0x0c2a		/* PIO15-PIO0 Direction */ +#define SC520_PIODIR31_16	0x0c2c		/* PIO31-PIO16 Direction */ +#define SC520_PIODATA15_0	0x0c30		/* PIO15-PIO0 Data */ +#define SC520_PIODATA31_16	0x0c32		/* PIO31-PIO16 Data */ +#define SC520_PIOSET15_0	0x0c34		/* PIO15-PIO0 Set */ +#define SC520_PIOSET31_16	0x0c36		/* PIO31-PIO16 Set */ +#define SC520_PIOCLR15_0	0x0c38		/* PIO15-PIO0 Clear */ +#define SC520_PIOCLR31_16	0x0c3a		/* PIO31-PIO16 Clear */ +#define SC520_SWTMRMILLI 	0x0c60		/* Software Timer Millisecond Count */ +#define SC520_SWTMRMICRO 	0x0c62		/* Software Timer Microsecond Count */ +#define SC520_SWTMRCFG   	0x0c64		/* Software Timer Configuration */ +#define SC520_GPTMRSTA		0x0c70		/* GP Timers Status Register */ +#define SC520_GPTMR0CTL		0x0c72		/* GP Timer 0 Mode/Control Register */ +#define SC520_GPTMR0CNT		0x0c74		/* GP Timer 0 Count Register */ +#define SC520_GPTMR0MAXCMPA	0x0c76		/* GP Timer 0 Maxcount Compare A Register */ +#define SC520_GPTMR0MAXCMPB	0x0c78		/* GP Timer 0 Maxcount Compare B Register */ +#define SC520_GPTMR1CTL		0x0c7a		/* GP Timer 1 Mode/Control Register */ +#define SC520_GPTMR1CNT		0x0c7c		/* GP Timer 1 Count Register */ +#define SC520_GPTMR1MAXCMPA	0x0c7e		/* GP Timer 1 Maxcount Compare Register A */ +#define SC520_GPTMR1MAXCMPB	0x0c80		/* GP Timer 1 Maxcount Compare B Register */ +#define SC520_GPTMR2CTL		0x0c82		/* GP Timer 2 Mode/Control Register */ +#define SC520_GPTMR2CNT		0x0c84		/* GP Timer 2 Count Register */ +#define SC520_GPTMR2MAXCMPA	0x0c8e		/* GP Timer 2 Maxcount Compare A Register */ +#define SC520_WDTMRCTL		0x0cb0		/* Watchdog Timer Control Register */ +#define SC520_WDTMRCNTL		0x0cb2		/* Watchdog Timer Count Low Register */ +#define SC520_WDTMRCNTH		0x0cb4		/* Watchdog Timer Count High Register */ +#define SC520_UART1CTL		0x0cc0	        /* UART 1 General Control Register */ +#define SC520_UART1STA		0x0cc1	        /* UART 1 General Status Register */ +#define SC520_UART1FCRSHAD	0x0cc2	        /* UART 1 FIFO Control Shadow Register */ +#define SC520_UART2CTL		0x0cc4	        /* UART 2 General Control Register */ +#define SC520_UART2STA		0x0cc5	        /* UART 2 General Status Register */ +#define SC520_UART2FCRSHAD	0x0cc6	        /* UART 2 FIFO Control Shadow Register */ +#define SC520_PICICR		0x0d00		/* Interrupt Control Register */ +#define SC520_MPICMODE		0x0d02		/* Master PIC Interrupt Mode Register */ +#define SC520_SL1PICMODE	0x0d03		/* Slave 1 PIC Interrupt Mode Register */ +#define SC520_SL2PICMODE	0x0d04		/* Slave 2 PIC Interrupt Mode Register */ +#define SC520_SWINT16_1		0x0d08		/* Software Interrupt 16-1 Control Register */ +#define SC520_SWINT22_17	0x0d0a		/* Software Interrupt 22-17/NMI Control Register */ +#define SC520_INTPINPOL		0x0d10		/* Interrupt Pin Polarity Register */ +#define SC520_PCIHOSTMAP	0x0d14		/* PCI Host Bridge Interrupt Mappin Register */ +#define SC520_ECCMAP		0x0d18		/* ECC Interrupt Mapping Register */ +#define SC520_GPTMR0MAP		0x0d1a		/* GP Timer 0 Interrupt Mapping Register */ +#define SC520_GPTMR1MAP		0x0d1b		/* GP Timer 1 Interrupt Mapping Register */ +#define SC520_GPTMR2MAP		0x0d1c		/* GP Timer 2 Interrupt Mapping Register */ +#define SC520_PIT0MAP		0x0d20		/* PIT0 Interrupt Mapping Register */ +#define SC520_PIT1MAP		0x0d21		/* PIT1 Interrupt Mapping Register */ +#define SC520_PIT2MAP		0x0d22		/* PIT2 Interrupt Mapping Register */ +#define SC520_UART1MAP		0x0d28		/* UART 1 Interrupt Mapping Register */ +#define SC520_UART2MAP		0x0d29		/* UART 2 Interrupt Mapping Register */ +#define SC520_PCIINTAMAP	0x0d30		/* PCI Interrupt A Mapping Register */ +#define SC520_PCIINTBMAP	0x0d31		/* PCI Interrupt B Mapping Register */ +#define SC520_PCIINTCMAP	0x0d32		/* PCI Interrupt C Mapping Register */ +#define SC520_PCIINTDMAP	0x0d33		/* PCI Interrupt D Mapping Register */ +#define SC520_DMABCINTMAP	0x0d40		/* DMA Buffer Chaining Interrupt Mapping Register */ +#define SC520_SSIMAP		0x0d41		/* SSI Interrupt Mapping Register */ +#define SC520_WDTMAP		0x0d42		/* Watchdog Timer Interrupt Mapping Register */ +#define SC520_RTCMAP		0x0d43		/* RTC Interrupt Mapping Register */ +#define SC520_WPVMAP		0x0d44		/* Write-Protect Interrupt Mapping Register */ +#define SC520_ICEMAP		0x0d45		/* AMDebug JTAG RX/TX Interrupt Mapping Register */ +#define SC520_FERRMAP		0x0d46		/* Floating Point Error Interrupt Mapping Register */ +#define SC520_GP0IMAP		0x0d50		/* GPIRQ0 Interrupt Mapping Register */ +#define SC520_GP1IMAP		0x0d51		/* GPIRQ1 Interrupt Mapping Register */ +#define SC520_GP2IMAP		0x0d52		/* GPIRQ2 Interrupt Mapping Register */ +#define SC520_GP3IMAP		0x0d53		/* GPIRQ3 Interrupt Mapping Register */ +#define SC520_GP4IMAP		0x0d54		/* GPIRQ4 Interrupt Mapping Register */ +#define SC520_GP5IMAP		0x0d55		/* GPIRQ5 Interrupt Mapping Register */ +#define SC520_GP6IMAP		0x0d56		/* GPIRQ6 Interrupt Mapping Register */ +#define SC520_GP7IMAP		0x0d57		/* GPIRQ7 Interrupt Mapping Register */ +#define SC520_GP8IMAP		0x0d58		/* GPIRQ8 Interrupt Mapping Register */ +#define SC520_GP9IMAP		0x0d59		/* GPIRQ9 Interrupt Mapping Register */ +#define SC520_GP10IMAP		0x0d5a		/* GPIRQ10 Interrupt Mapping Register */ +#define SC520_SYSINFO		0x0d70		/* System Board Information Register */ +#define SC520_RESCFG		0x0d72		/* Reset Configuration Register */ +#define SC520_RESSTA		0x0d74		/* Reset Status Register */ +#define SC520_GPDMAMMIO		0x0d81		/* GP-DMA Memory-Mapped I/O Register */ +#define SC520_GPDMAEXTCHMAPA	0x0d82		/* GP-DMA Resource Channel Map A */ +#define SC520_GPDMAEXTCHMAPB	0x0d84		/* GP-DMA Resource Channel Map B */ +#define SC520_GPDMAEXTPG0	0x0d86		/* GP-DMA Channel 0 Extended Page */ +#define SC520_GPDMAEXTPG1	0x0d87		/* GP-DMA Channel 1 Extended Page */ +#define SC520_GPDMAEXTPG2	0x0d88		/* GP-DMA Channel 2 Extended Page */ +#define SC520_GPDMAEXTPG3	0x0d89		/* GP-DMA Channel 3 Extended Page */ +#define SC520_GPDMAEXTPG5	0x0d8a		/* GP-DMA Channel 5 Extended Page */ +#define SC520_GPDMAEXTPG6	0x0d8b		/* GP-DMA Channel 6 Extended Page */ +#define SC520_GPDMAEXTPG7	0x0d8c		/* GP-DMA Channel 7 Extended Page */ +#define SC520_GPDMAEXTTC3	0x0d90		/* GP-DMA Channel 3 Extender Transfer count */ +#define SC520_GPDMAEXTTC5	0x0d91		/* GP-DMA Channel 5 Extender Transfer count */ +#define SC520_GPDMAEXTTC6	0x0d92		/* GP-DMA Channel 6 Extender Transfer count */ +#define SC520_GPDMAEXTTC7	0x0d93		/* GP-DMA Channel 7 Extender Transfer count */ +#define SC520_GPDMABCCTL	0x0d98		/* Buffer Chaining Control */ +#define SC520_GPDMABCSTA	0x0d99		/* Buffer Chaining Status */ +#define SC520_GPDMABSINTENB	0x0d9a		/* Buffer Chaining Interrupt Enable */ +#define SC520_GPDMABCVAL	0x0d9b		/* Buffer Chaining Valid */ +#define SC520_GPDMANXTADDL3	0x0da0		/* GP-DMA Channel 3 Next Address Low */ +#define SC520_GPDMANXTADDH3	0x0da2		/* GP-DMA Channel 3 Next Address High */ +#define SC520_GPDMANXTADDL5	0x0da4		/* GP-DMA Channel 5 Next Address Low */ +#define SC520_GPDMANXTADDH5	0x0da6		/* GP-DMA Channel 5 Next Address High */ +#define SC520_GPDMANXTADDL6	0x0da8		/* GP-DMA Channel 6 Next Address Low */ +#define SC520_GPDMANXTADDH6	0x0daa		/* GP-DMA Channel 6 Next Address High */ +#define SC520_GPDMANXTADDL7	0x0dac		/* GP-DMA Channel 7 Next Address Low */ +#define SC520_GPDMANXTADDH7	0x0dae		/* GP-DMA Channel 7 Next Address High */ +#define SC520_GPDMANXTTCL3	0x0db0		/* GP-DMA Channel 3 Next Transfer Count Low */ +#define SC520_GPDMANXTTCH3	0x0db2		/* GP-DMA Channel 3 Next Transfer Count High */ +#define SC520_GPDMANXTTCL5	0x0db4		/* GP-DMA Channel 5 Next Transfer Count Low */ +#define SC520_GPDMANXTTCH5	0x0db6		/* GP-DMA Channel 5 Next Transfer Count High */ +#define SC520_GPDMANXTTCL6	0x0db8		/* GP-DMA Channel 6 Next Transfer Count Low */ +#define SC520_GPDMANXTTCH6	0x0dba		/* GP-DMA Channel 6 Next Transfer Count High */ +#define SC520_GPDMANXTTCL7	0x0dbc		/* GP-DMA Channel 7 Next Transfer Count Low */ +#define SC520_GPDMANXTTCH7	0x0dbe		/* GP-DMA Channel 7 Next Transfer Count High */ + +/* MMCR Register bits (not all of them :) ) */ + +/* BITS for SC520_ADDDECCTL: */ +#define WPV_INT_ENB		0x80		/* Write-Protect Violation Interrupt Enable */ +#define IO_HOLE_DEST		0x10		/* I/O Hole Access Destination */ +#define RTC_DIS			0x04		/* RTC Disable */ +#define UART2_DIS		0x02		/* UART2 Disable */ +#define UART1_DIS		0x01		/* UART1 Disable */ + +/* bus mapping constants (used for PCI core initialization) */																																																 /* bus mapping constants */ +#define SC520_REG_ADDR		0x00000cf8      +#define SC520_REG_DATA		0x00000cfc + + +#define SC520_ISA_MEM_PHYS	0x00000000 +#define SC520_ISA_MEM_BUS	0x00000000 +#define SC520_ISA_MEM_SIZE	0x01000000 + +#define SC520_ISA_IO_PHYS	0x00000000 +#define SC520_ISA_IO_BUS	0x00000000 +#define SC520_ISA_IO_SIZE	0x00001000 + +/* PCI I/O space from 0x1000 to 0xfdff */ +#define SC520_PCI_IO_PHYS	0x00001000 +#define SC520_PCI_IO_BUS	0x00001000 +#define SC520_PCI_IO_SIZE	0x0000ee00 + +/* system memory from 0x00000000 to 0x0fffffff */ +#define	SC520_PCI_MEMORY_PHYS	0x00000000 +#define	SC520_PCI_MEMORY_BUS	0x00000000 +#define SC520_PCI_MEMORY_SIZE	0x10000000 + +/* PCI bus memory from 0x10000000 to 0x27ffffff */ +#define SC520_PCI_MEM_PHYS	0x10000000 +#define SC520_PCI_MEM_BUS       0x10000000 +#define SC520_PCI_MEM_SIZE	0x18000000 + +/* 0x28000000 - 0x3fffffff is used by the flash banks */ + +/* 0x40000000 - 0xffffffff is not adressable by the SC520 */ + +/* utility functions */ +void write_mmcr_byte(u16 mmcr, u8 data); +void write_mmcr_word(u16 mmcr, u16 data); +void write_mmcr_long(u16 mmcr, u32 data); +u8 read_mmcr_byte(u16 mmcr); +u16 read_mmcr_word(u16 mmcr); +u32 read_mmcr_long(u16 mmcr); + +void init_sc520(void); +unsigned long init_sc520_dram(void); +void pci_sc520_init(struct pci_controller *hose); + +#endif diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h new file mode 100644 index 000000000..d8c503ccb --- /dev/null +++ b/include/asm-i386/io.h @@ -0,0 +1,207 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include <linux/config.h> + +/* + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + *		Linus + */ + + /* +  *  Bit simplified and optimized by Jan Hubicka +  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999. +  * +  *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added, +  *  isa_read[wl] and isa_write[wl] fixed +  *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br> +  */ + +#define IO_SPACE_LIMIT 0xffff + + +#ifdef __KERNEL__ + + +/* + * readX/writeX() are used to access memory mapped devices. On some + * architectures the memory mapped IO stuff needs to be accessed + * differently. On the x86 architecture, we just read/write the + * memory location directly. + */ + +#define readb(addr) (*(volatile unsigned char *) (addr)) +#define readw(addr) (*(volatile unsigned short *) (addr)) +#define readl(addr) (*(volatile unsigned int *) (addr)) +#define __raw_readb readb +#define __raw_readw readw +#define __raw_readl readl + +#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b)) +#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b)) +#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b)) +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel + +#define memset_io(a,b,c)	memset((a),(b),(c)) +#define memcpy_fromio(a,b,c)	memcpy((a),(b),(c)) +#define memcpy_toio(a,b,c)	memcpy((a),(b),(c)) + +/* + * ISA space is 'always mapped' on a typical x86 system, no need to + * explicitly ioremap() it. The fact that the ISA IO space is mapped + * to PAGE_OFFSET is pure coincidence - it does not mean ISA values + * are physical addresses. The following constant pointer can be + * used as the IO-area pointer (it can be iounmapped as well, so the + * analogy with PCI is quite large): + */ +#define isa_readb(a) readb((a)) +#define isa_readw(a) readw((a)) +#define isa_readl(a) readl((a)) +#define isa_writeb(b,a) writeb(b,(a)) +#define isa_writew(w,a) writew(w,(a)) +#define isa_writel(l,a) writel(l,(a)) +#define isa_memset_io(a,b,c)		memset_io((a),(b),(c)) +#define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),(b),(c)) +#define isa_memcpy_toio(a,b,c)		memcpy_toio((a),(b),(c)) + + +  +static inline int check_signature(unsigned long io_addr, +	const unsigned char *signature, int length) +{ +	int retval = 0; +	do { +		if (readb(io_addr) != *signature) +			goto out; +		io_addr++; +		signature++; +		length--; +	} while (length); +	retval = 1; +out: +	return retval; +} + +/** + *	isa_check_signature		-	find BIOS signatures + *	@io_addr: mmio address to check  + *	@signature:  signature block + *	@length: length of signature + * + *	Perform a signature comparison with the ISA mmio address io_addr. + *	Returns 1 on a match. + * + *	This function is deprecated. New drivers should use ioremap and + *	check_signature. + */ +  + +static inline int isa_check_signature(unsigned long io_addr, +	const unsigned char *signature, int length) +{ +	int retval = 0; +	do { +		if (isa_readb(io_addr) != *signature) +			goto out; +		io_addr++; +		signature++; +		length--; +	} while (length); +	retval = 1; +out: +	return retval; +} + +#endif /* __KERNEL__ */ + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:" +#else +#define __SLOW_DOWN_IO "\noutb %%al,$0x80" +#endif + +#ifdef REALLY_SLOW_IO +#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO +#else +#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + + +/* + * Talk about misusing macros.. + */ +#define __OUT1(s,x) \ +static inline void out##s(unsigned x value, unsigned short port) { + +#define __OUT2(s,s1,s2) \ +__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" + + +#define __OUT(s,s1,x) \ +__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \ +__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));}  + +#define __IN1(s) \ +static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; + +#define __IN2(s,s1,s2) \ +__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" + +#define __IN(s,s1,i...) \ +__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ +__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; }  + +#define __INS(s) \ +static inline void ins##s(unsigned short port, void * addr, unsigned long count) \ +{ __asm__ __volatile__ ("rep ; ins" #s \ +: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } + +#define __OUTS(s) \ +static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ +{ __asm__ __volatile__ ("rep ; outs" #s \ +: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } + +#define RETURN_TYPE unsigned char +__IN(b,"") +#undef RETURN_TYPE +#define RETURN_TYPE unsigned short +__IN(w,"") +#undef RETURN_TYPE +#define RETURN_TYPE unsigned int +__IN(l,"") +#undef RETURN_TYPE + +__OUT(b,"b",char) +__OUT(w,"w",short) +__OUT(l,,int) + +__INS(b) +__INS(w) +__INS(l) + +__OUTS(b) +__OUTS(w) +__OUTS(l) + +#endif diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h new file mode 100644 index 000000000..15c165b72 --- /dev/null +++ b/include/asm-i386/pci.h @@ -0,0 +1,31 @@ + + +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _PCI_I386_H_ +#define _PCI_I386_H_	1 + +void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data); + +#endif diff --git a/include/asm-i386/posix_types.h b/include/asm-i386/posix_types.h new file mode 100644 index 000000000..5529f3270 --- /dev/null +++ b/include/asm-i386/posix_types.h @@ -0,0 +1,80 @@ +#ifndef __ARCH_I386_POSIX_TYPES_H +#define __ARCH_I386_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc.  Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned short	__kernel_dev_t; +typedef unsigned long	__kernel_ino_t; +typedef unsigned short	__kernel_mode_t; +typedef unsigned short	__kernel_nlink_t; +typedef long		__kernel_off_t; +typedef int		__kernel_pid_t; +typedef unsigned short	__kernel_ipc_pid_t; +typedef unsigned short	__kernel_uid_t; +typedef unsigned short	__kernel_gid_t; +typedef unsigned int	__kernel_size_t; +typedef int		__kernel_ssize_t; +typedef int		__kernel_ptrdiff_t; +typedef long		__kernel_time_t; +typedef long		__kernel_suseconds_t; +typedef long		__kernel_clock_t; +typedef int		__kernel_daddr_t; +typedef char *		__kernel_caddr_t; +typedef unsigned short	__kernel_uid16_t; +typedef unsigned short	__kernel_gid16_t; +typedef unsigned int	__kernel_uid32_t; +typedef unsigned int	__kernel_gid32_t; + +typedef unsigned short	__kernel_old_uid_t; +typedef unsigned short	__kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long	__kernel_loff_t; +#endif + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) +	int	val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +	int	__val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef	__FD_SET +#define __FD_SET(fd,fdsetp) \ +		__asm__ __volatile__("btsl %1,%0": \ +			"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd))) + +#undef	__FD_CLR +#define __FD_CLR(fd,fdsetp) \ +		__asm__ __volatile__("btrl %1,%0": \ +			"=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd))) + +#undef	__FD_ISSET +#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \ +		unsigned char __result; \ +		__asm__ __volatile__("btl %1,%2 ; setb %0" \ +			:"=q" (__result) :"r" ((int) (fd)), \ +			"m" (*(__kernel_fd_set *) (fdsetp))); \ +		__result; })) + +#undef	__FD_ZERO +#define __FD_ZERO(fdsetp) \ +do { \ +	int __d0, __d1; \ +	__asm__ __volatile__("cld ; rep ; stosl" \ +			:"=m" (*(__kernel_fd_set *) (fdsetp)), \ +			  "=&c" (__d0), "=&D" (__d1) \ +			:"a" (0), "1" (__FDSET_LONGS), \ +			"2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \ +} while (0) + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif diff --git a/include/asm-i386/ppcboot-i386.h b/include/asm-i386/ppcboot-i386.h new file mode 100644 index 000000000..704526e2f --- /dev/null +++ b/include/asm-i386/ppcboot-i386.h @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _PPCBOOT_I386_H_ +#define _PPCBOOT_I386_H_	1 + +/* for the following variables, see start.S */ +extern ulong i386boot_start;	    /* code start (in flash) */ +extern ulong i386boot_end;	    /* code end (in flash) */ +extern ulong i386boot_romdata_start;/* datasegment in flash (also code+rodata end) */ +extern ulong i386boot_romdata_dest; /* data location segment in ram */ +extern ulong i386boot_romdata_size; /* size of data segment */ +extern ulong i386boot_bss_start;    /* bss start */ +extern ulong i386boot_bss_size;     /* bss size */ +extern ulong i386boot_stack_end;    /* first usable RAM address after bss and stack */ +extern ulong i386boot_ram_end;      /* end of ram */ + +extern ulong i386boot_realmode;     /* start of realmode entry code */ +extern ulong i386boot_realmode_size;/* size of realmode entry code */ +extern ulong i386boot_bios;         /* start of BIOS emulation code */ +extern ulong i386boot_bios_size;    /* size of BIOS emulation code */ + + +/* cpu/.../cpu.c */ +int cpu_init(void); +int timer_init(void); + +/* board/.../... */ +int	board_init(void); +int	dram_init (void); + + +#endif	/* _PPCBOOT_I386_H_ */ diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h new file mode 100644 index 000000000..d99e46400 --- /dev/null +++ b/include/asm-i386/ptrace.h @@ -0,0 +1,66 @@ +#ifndef _I386_PTRACE_H +#define _I386_PTRACE_H + +#define EBX 0 +#define ECX 1 +#define EDX 2 +#define ESI 3 +#define EDI 4 +#define EBP 5 +#define EAX 6 +#define DS 7 +#define ES 8 +#define FS 9 +#define GS 10 +#define ORIG_EAX 11 +#define EIP 12 +#define CS  13 +#define EFL 14 +#define UESP 15 +#define SS   16 +#define FRAME_SIZE 17 + +/* this struct defines the way the registers are stored on the  +   stack during a system call. */ + +struct pt_regs { +	long ebx; +	long ecx; +	long edx; +	long esi; +	long edi; +	long ebp; +	long eax; +	int  xds; +	int  xes; +	int  xfs; +	int  xgs; +	long orig_eax; +	long eip; +	int  xcs; +	long eflags; +	long esp; +	int  xss; +}  __attribute__ ((packed)); + + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +#define PTRACE_GETREGS            12 +#define PTRACE_SETREGS            13 +#define PTRACE_GETFPREGS          14 +#define PTRACE_SETFPREGS          15 +#define PTRACE_GETFPXREGS         18 +#define PTRACE_SETFPXREGS         19 + +#define PTRACE_SETOPTIONS         21 + +/* options set using PTRACE_SETOPTIONS */ +#define PTRACE_O_TRACESYSGOOD     0x00000001 + +#ifdef __KERNEL__ +#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) +#define instruction_pointer(regs) ((regs)->eip) +extern void show_regs(struct pt_regs *); +#endif + +#endif diff --git a/include/asm-i386/realmode.h b/include/asm-i386/realmode.h new file mode 100644 index 000000000..fcb76c336 --- /dev/null +++ b/include/asm-i386/realmode.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_REALMODE_H_ +#define __ASM_REALMODE_H_ +#include <asm/ptrace.h> + +int bios_setup(void); +int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out); + +#endif diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h new file mode 100644 index 000000000..c37822248 --- /dev/null +++ b/include/asm-i386/string.h @@ -0,0 +1,30 @@ +#ifndef __ASM_I386_STRING_H +#define __ASM_I386_STRING_H + +/* + * We don't do inline string functions, since the + * optimised inline asm versions are not small. + */ + +#define __HAVE_ARCH_STRRCHR +extern char * strrchr(const char * s, int c); + +#define __HAVE_ARCH_STRCHR +extern char * strchr(const char * s, int c); + +#define __HAVE_ARCH_MEMCPY +extern void * memcpy(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMMOVE +extern void * memmove(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMCHR +extern void * memchr(const void *, int, __kernel_size_t); + +#define __HAVE_ARCH_MEMSET +extern void * memset(void *, int, __kernel_size_t); + +#define __HAVE_ARCH_MEMZERO +extern void memzero(void *ptr, __kernel_size_t n); + +#endif diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h new file mode 100644 index 000000000..bb100ec4e --- /dev/null +++ b/include/asm-i386/types.h @@ -0,0 +1,51 @@ +#ifndef __ASM_I386_TYPES_H +#define __ASM_I386_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide.  */ + +typedef u32 dma_addr_t; + +#endif /* __KERNEL__ */ + +#endif + diff --git a/include/asm-i386/u-boot.h b/include/asm-i386/u-boot.h new file mode 100644 index 000000000..554bc85ea --- /dev/null +++ b/include/asm-i386/u-boot.h @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + *  + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _U_BOOT_H_ +#define _U_BOOT_H_	1 + +typedef struct bd_info { +	unsigned long	bi_memstart;	/* start of DRAM memory */ +	unsigned long	bi_memsize;	/* size	 of DRAM memory in bytes */ +	unsigned long	bi_flashstart;	/* start of FLASH memory */ +	unsigned long	bi_flashsize;	/* size	 of FLASH memory */ +	unsigned long	bi_flashoffset; /* reserved area for startup monitor */ +	unsigned long	bi_sramstart;	/* start of SRAM memory */ +	unsigned long	bi_sramsize;	/* size	 of SRAM memory */ +	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */ +	unsigned long	bi_ip_addr;	/* IP Address */ +	unsigned char	bi_enetaddr[6];	/* Ethernet adress */ +	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */ +	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */ +	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */ +	unsigned long	bi_baudrate;	/* Console Baudrate */ +	struct environment_s	       *bi_env; +	struct				/* RAM configuration */ +	{  +		ulong start; +		ulong size; +	}bi_dram[CONFIG_NR_DRAM_BANKS]; +} bd_t; + +#define bi_env_data bi_env->data +#define bi_env_crc  bi_env->crc + +#endif	/* _U_BOOT_H_ */ diff --git a/include/asm-i386/zimage.h b/include/asm-i386/zimage.h new file mode 100644 index 000000000..688682611 --- /dev/null +++ b/include/asm-i386/zimage.h @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ASM_ZIMAGE_H_ +#define _ASM_ZIMAGE_H_ + +/* linux i386 zImage/bzImage header. Offsets relative to  + * the start of the image */ + +#define CMD_LINE_MAGIC_OFF  0x020 /* Magic 0xa33f if the offset below is valid */ +#define CMD_LINE_OFFSET_OFF 0x022 /* Offset to comandline */ +#define SETUP_SECTS_OFF     0x1F1 /* The size of the setup in sectors */ +#define ROOT_FLAGS_OFF      0x1F2 /* If set, the root is mounted readonly */ +#define VID_MODE_OFF        0x1FA /* Video mode control */ +#define ROOT_DEV_OFF        0x1FC /* Default root device number */ +#define BOOT_FLAG_OFF       0x1FE /* 0xAA55 magic number */ +#define HEADER_OFF          0x202 /* Magic signature "HdrS" */ +#define VERSION_OFF         0x206 /* Boot protocol version supported */ +#define REALMODE_SWTCH_OFF  0x208 /* Boot loader hook (see below) */ +#define START_SYS_OFF       0x20C /* Points to kernel version string */ +#define TYPE_OF_LOADER_OFF  0x210 /* Boot loader identifier */ +#define LOADFLAGS_OFF       0x211 /* Boot protocol option flags */ +#define SETUP_MOVE_SIZE_OFF 0x212 /* Move to high memory size (used with hooks) */ +#define CODE32_START_OFF    0x214 /* Boot loader hook (see below) */ +#define RAMDISK_IMAGE_OFF   0x218 /* initrd load address (set by boot loader) */ +#define RAMDISK_SIZE_OFF    0x21C /* initrd size (set by boot loader) */ +#define HEAP_END_PTR_OFF    0x224 /* Free memory after setup end */ +#define CMD_LINE_PTR_OFF    0x228 /* 32-bit pointer to the kernel command line */ + + +#define HEAP_FLAG           0x80 +#define BIG_KERNEL_FLAG     0x01 + +/* magic numbers */ +#define KERNEL_MAGIC        0xaa55 +#define KERNEL_V2_MAGIC     0x53726448 +#define COMMAND_LINE_MAGIC  0xA33F + +/* limits */ +#define BZIMAGE_MAX_SIZE   15*1024*1024     /* 15MB */ +#define ZIMAGE_MAX_SIZE    512*1024         /* 512k */ +#define SETUP_MAX_SIZE     32768 + +#define SETUP_START_OFFSET 0x200 +#define BZIMAGE_LOAD_ADDR  0x100000  +#define ZIMAGE_LOAD_ADDR   0x10000 +	 +void *load_zimage(char *image, unsigned long kernel_size,  +		  unsigned long initrd_addr, unsigned long initrd_size, +		  int auto_boot); + +void boot_zimage(void *setup_base); +image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size); + +#endif diff --git a/include/cmd_confdefs.h b/include/cmd_confdefs.h index a5308b693..25f386b95 100644 --- a/include/cmd_confdefs.h +++ b/include/cmd_confdefs.h @@ -75,8 +75,8 @@  #define CFG_CMD_FPGA	0x0000010000000000	/* FPGA configuration Support   */  #define CFG_CMD_HWFLOW	0x0000020000000000	/* RTS/CTS hw flow control	*/  #define CFG_CMD_SAVES	0x0000040000000000	/* save S record dump		*/ -#define CFG_CMD_VFD	0x0000080000000000	/* Display bitmap on VFD display*/  #define CFG_CMD_SPI	0x0000100000000000	/* SPI utility			*/ +#define CFG_CMD_FDOS    0x0000200000000000      /* Floppy DOS support           */  #define CFG_CMD_ALL	0xFFFFFFFFFFFFFFFF	/* ALL commands			*/ @@ -96,6 +96,7 @@  			CFG_CMD_EEPROM	| \  			CFG_CMD_ELF	| \  			CFG_CMD_FDC	| \ +                        CFG_CMD_FDOS    | \  			CFG_CMD_HWFLOW	| \  			CFG_CMD_I2C	| \  			CFG_CMD_IDE	| \ @@ -110,9 +111,9 @@  			CFG_CMD_SAVES	| \  			CFG_CMD_SCSI	| \  			CFG_CMD_SDRAM	| \ +			CFG_CMD_SPI	| \  			CFG_CMD_USB	| \ -			CFG_CMD_VFD	| \ -			CFG_CMD_SPI	) +			CFG_CMD_VFD	)  /* Default configuration   */ diff --git a/include/cmd_fdos.h b/include/cmd_fdos.h new file mode 100644 index 000000000..a444c7abc --- /dev/null +++ b/include/cmd_fdos.h @@ -0,0 +1,55 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Dos floppy support + */ +#ifndef	_CMD_FDOS_H +#define	_CMD_FDOS_H + +#include <common.h> +#include <command.h> + + +#if (CONFIG_COMMANDS & CFG_CMD_FDOS) + +#define CMD_TBL_FDOS_BOOT	MK_CMD_TBL_ENTRY(       \ +	"fdosboot", 5,	3,	0,	do_fdosboot,    \ +	"fdosboot- boot from a dos floppy file\n",     \ +	"[loadAddr] [filename]\n"                       \ +), +#define CMD_TBL_FDOS_LS	        MK_CMD_TBL_ENTRY(       \ +	"fdosls", 5,	2,	0,	do_fdosls,      \ +	"fdosls  - list files in a directory\n",       \ +	"[directory]\n"                                 \ +), +int do_fdosboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_fdosls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#else +#define CMD_TBL_FDOS_BOOT +#define CMD_TBL_FDOS_LS +#endif + +#endif	/* _CMD_FDOS_H */ diff --git a/include/common.h b/include/common.h index 21101f105..a950cdcc4 100644 --- a/include/common.h +++ b/include/common.h @@ -130,10 +130,15 @@ int	getenv_r     (uchar *name, uchar *buf, unsigned len);  int	saveenv      (void);  #ifdef CONFIG_PPC		/* ARM version to be fixed! */  void inline setenv   (char *, char *); +#else +void    setenv       (char *, char *);  #endif /* CONFIG_PPC */  #ifdef CONFIG_ARM  # include <asm/u-boot-arm.h>	/* ARM version to be fixed! */  #endif /* CONFIG_ARM */ +#ifdef CONFIG_I386		/* x86 version to be fixed! */ +# include <asm/ppcboot-i386.h>   +#endif /* CONFIG_I386 */  void    pci_init      (void);  void    pciinfo       (int, int); diff --git a/include/configs/LANTEC.h b/include/configs/LANTEC.h index c7c78ad0c..fe9ee228e 100644 --- a/include/configs/LANTEC.h +++ b/include/configs/LANTEC.h @@ -90,6 +90,7 @@  					     & ~CFG_CMD_EEPROM	\  					     & ~CFG_CMD_ELF	\  					     & ~CFG_CMD_FDC	\ +					     & ~CFG_CMD_FDOS	\  					     & ~CFG_CMD_HWFLOW	\  					     & ~CFG_CMD_I2C	\  					     & ~CFG_CMD_IDE	\ diff --git a/include/configs/MPC8260ADS.h b/include/configs/MPC8260ADS.h index 14ad31394..b4d8406aa 100644 --- a/include/configs/MPC8260ADS.h +++ b/include/configs/MPC8260ADS.h @@ -112,6 +112,7 @@  				 CFG_CMD_EEPROM | \  				 CFG_CMD_ELF    | \  				 CFG_CMD_FDC	| \ +				 CFG_CMD_FDOS	| \  				 CFG_CMD_HWFLOW	| \  				 CFG_CMD_IDE	| \  				 CFG_CMD_JFFS2	| \ diff --git a/include/configs/ep8260.h b/include/configs/ep8260.h index 5db1f13a1..1285326f4 100644 --- a/include/configs/ep8260.h +++ b/include/configs/ep8260.h @@ -276,6 +276,7 @@  					~CFG_CMD_DOC    & \  					~CFG_CMD_EEPROM & \  					~CFG_CMD_FDC    & \ +					~CFG_CMD_FDOS	& \  					~CFG_CMD_HWFLOW	& \  					~CFG_CMD_IDE    & \  					~CFG_CMD_JFFS2	& \ diff --git a/include/configs/hymod.h b/include/configs/hymod.h index af3ba686d..5d2bed6ab 100644 --- a/include/configs/hymod.h +++ b/include/configs/hymod.h @@ -141,6 +141,7 @@  					CFG_CMD_DOC	| \  					CFG_CMD_ELF	| \  					CFG_CMD_FDC	| \ +					CFG_CMD_FDOS	| \  					CFG_CMD_HWFLOW	| \  					CFG_CMD_IDE	| \  					CFG_CMD_JFFS2	| \ diff --git a/include/configs/sc520_cdp.h b/include/configs/sc520_cdp.h new file mode 100644 index 000000000..e7d6c7942 --- /dev/null +++ b/include/configs/sc520_cdp.h @@ -0,0 +1,210 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_X86		1	/* This is a X86 CPU		*/ + +#define CFG_SDRAM_PRECHARGE_DELAY 6     /* 6T */	 +#define CFG_SDRAM_REFRESH_RATE    78    /* 7.8uS (choices are 7.8, 15.6, 31.2 or 62.5uS) */ +#define CFG_SDRAM_RAS_CAS_DELAY   3     /* 3T */ + +/* define at most one of these */ +#undef CFG_SDRAM_CAS_LATENCY_2T +#define CFG_SDRAM_CAS_LATENCY_3T + +#define CFG_SC520_HIGH_SPEED    0       /* 100 or 133MHz */ +#define CFG_RESET_GENERIC       1       /* use tripple-fault to reset cpu */ +#undef  CFG_RESET_SC520                 /* use SC520 MMCR's to reset cpu */ +#undef  CFG_TIMER_SC520                 /* use SC520 swtimers */ +#define CFG_TIMER_GENERIC       1       /* use the i8254 PIT timers */ +#undef  CFG_TIMER_TSC                   /* use the Pentium TSC timers */ +#define  CFG_USE_SIO_UART       0       /* prefer the uarts on the SIO to those +					 * in the SC520 on the CDP */ + +#define CFG_STACK_SIZE          0x8000  /* Size of bootloader stack */ + +#define CONFIG_SHOW_BOOT_PROGRESS 1 +#define CONFIG_LAST_STAGE_INIT    1 + +/* + * Size of malloc() pool + */ +#define CONFIG_MALLOC_SIZE	(CFG_ENV_SIZE + 128*1024) + + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE +#define CFG_ENV_IS_NOWHERE 1 +#undef CFG_ENV_IS_IN_FLASH  +#undef CFG_ENV_IS_IN_NVRAM  +#undef CFG_ENV_IS_INEEPROM + +#define CONFIG_BAUDRATE		9600 + +#define CONFIG_COMMANDS         (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_JFFS2 | CFG_CMD_IDE | CFG_CMD_NET) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define CONFIG_BOOTDELAY	15 +#define CONFIG_BOOTARGS    	"root=/dev/mtdblock0 console=ttyS0,9600" +/* #define CONFIG_BOOTCOMMAND	"bootm 38000000" */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE	115200		/* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX	2		/* which serial port to use */ +#endif + +#define CFG_JFFS2_FIRST_BANK    0           /* use for JFFS2 */ +#define CFG_JFFS2_NUM_BANKS     1           /*  */ + +/* + * Miscellaneous configurable options + */ +#define	CFG_LONGHELP				/* undef to save memory		*/ +#define	CFG_PROMPT		"boot > "	/* Monitor Command Prompt	*/ +#define	CFG_CBSIZE		256		/* Console I/O Buffer Size	*/ +#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define	CFG_MAXARGS		16		/* max number of command args	*/ +#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/ + +#define CFG_MEMTEST_START	0x00100000	/* memtest works on	*/ +#define CFG_MEMTEST_END		0x01000000	/* 1 ... 16 MB in DRAM	*/ + +#undef  CFG_CLKS_IN_HZ		/* everything, incl board info, in Hz */ + +#define	CFG_LOAD_ADDR		0x38000000	/* default load address	*/ + +#define	CFG_HZ			1024		/* incrementer freq: 1kHz */ + +						/* valid baudrates */ +#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 } + + +/*----------------------------------------------------------------------- + * Physical Memory Map + */ +#define CONFIG_NR_DRAM_BANKS	4	   /* we have 4 banks of DRAM */ + + +#define PHYS_FLASH_1		0x38000000 /* Flash Bank #1 */ +#define PHYS_FLASH_SIZE		0x00800000 /* 8 MB */ + +#define CFG_FLASH_BASE		PHYS_FLASH_1 + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ +#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks		*/ +#define CFG_MAX_FLASH_SECT	64	/* max number of sectors on one chip	*/ + +/* timeout values are in ticks */ +#define CFG_FLASH_ERASE_TOUT	(2*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT	(2*CFG_HZ) /* Timeout for Flash Write */ + +#define	CFG_ENV_IS_IN_FLASH	1 +#define CFG_ENV_ADDR		(PHYS_FLASH_1 + 0x7a0000)	/* Addr of Environment Sector	*/ +#define CFG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/ + + +/*----------------------------------------------------------------------- + * Device drivers + */ +#define CONFIG_NET_MULTI        /* Multi ethernet cards support */ +#define CONFIG_PCNET +#define CONFIG_PCNET_79C973 +#define CONFIG_PCNET_79C975 +#define PCNET_HAS_PROM         1 +/************************************************************ + * IDE/ATA stuff + ************************************************************/ +#define CFG_IDE_MAXBUS		2   /* max. 2 IDE busses	*/ +#define CFG_IDE_MAXDEVICE	(CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */ + +#define CFG_ATA_IDE0_OFFSET	0x01F0	/* ide0 offste */ +#define CFG_ATA_IDE1_OFFSET	0x0170	/* ide1 offset */ +#define CFG_ATA_DATA_OFFSET	0	/* data reg offset	*/ +#define CFG_ATA_REG_OFFSET	0	/* reg offset */ +#define CFG_ATA_ALT_OFFSET	0x200	/* alternate register offset */ + +#undef	CONFIG_IDE_8xx_DIRECT		/* no pcmcia interface required */ +#undef	CONFIG_IDE_LED			/* no led for ide supported	*/ +#undef  CONFIG_IDE_RESET		/* reset for ide unsupported...	*/ +#undef  CONFIG_IDE_RESET_ROUTINE	/* no special reset function */ + +/************************************************************ + * ATAPI support (experimental) + ************************************************************/ +#define CONFIG_ATAPI			/* enable ATAPI Support */ + +/************************************************************ + * DISK Partition support + ************************************************************/ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION /* Experimental */ + +/************************************************************ + * Keyboard support + ************************************************************/ +#define CONFIG_ISA_KEYBOARD + +#if 0 +/************************************************************ + * Video support + ************************************************************/ +#define CONFIG_VIDEO			/*To enable video controller support */ +#define CONFIG_VIDEO_CT69000 +#define CONFIG_CFB_CONSOLE +#define CONFIG_VIDEO_LOGO +#define CONFIG_CONSOLE_EXTRA_INFO +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VIDEO_ONBOARD		/* Video controller is on-board */ +#endif + +/************************************************************ + * RTC + ***********************************************************/ +#define CONFIG_RTC_MC146818 +#undef CONFIG_WATCHDOG			/* watchdog disabled		*/ + +/* + * PCI stuff + */ +#define CONFIG_PCI                                /* include pci support */ +#define CONFIG_PCI_PNP                            /* pci plug-and-play */ +#define CONFIG_PCI_SCAN_SHOW + +#endif	/* __CONFIG_H */ diff --git a/include/fdc.h b/include/fdc.h new file mode 100644 index 000000000..7892b0e25 --- /dev/null +++ b/include/fdc.h @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2002 + * Stäubli Faverges - <www.staubli.com> + * Pierre AUBERT  p.aubert@staubli.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _FDC_H_ +#define _FDC_H_ + + + +/* Functions prototype                                                       */ +int fdc_fdos_init (int drive); +int fdc_fdos_seek (int where); +int fdc_fdos_read (void *buffer, int len); + +int dos_open(char *name); +int dos_read (ulong addr); +int dos_dir (void); + + + +#endif diff --git a/include/linux/stat.h b/include/linux/stat.h index 9fd32062d..13899c97c 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h @@ -67,7 +67,7 @@ struct stat {  #endif	/* __PPC__ */ -#ifdef	__ARM__ +#if defined (__ARM__) || defined (__I386__)  struct stat {  	unsigned short st_dev; diff --git a/lib_i386/Makefile b/lib_i386/Makefile new file mode 100644 index 000000000..34994e544 --- /dev/null +++ b/lib_i386/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= lib$(ARCH).a + +AOBJS	= bios.o realmode_switch.o ic/sc520_asm.o + +COBJS	= board.o bios_setup.o i386_linux.o zimage.o realmode.o \ +	  pci_type1.o ic/sc520.o ic/ali512x.o + +OBJS	= $(AOBJS) $(COBJS) + +$(LIB):	.depend $(OBJS) +	$(AR) crv $@ $(OBJS) + +######################################################################### + +.depend:	Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/lib_i386/bios.S b/lib_i386/bios.S new file mode 100644 index 000000000..2f5ea8cda --- /dev/null +++ b/lib_i386/bios.S @@ -0,0 +1,443 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Based on msbios.c from rolo 1.6: + *---------------------------------------------------------------------- + * (C) Copyright 2000 + * Sysgo Real-Time Solutions GmbH + * Klein-Winternheim, Germany + *---------------------------------------------------------------------- + */ + +/* + * During it's initialization phase, before switching to protected + * mode, the Linux Kernel makes a few BIOS calls. This won't work + * if the board does not have a BIOS. + * + * This is a very minimalisic BIOS that supplies just enough + * functionality to keep the Linux Kernel happy. It is NOT + * a general purpose replacement for a real BIOS !! + */ + +#define OFFS_ES      0 +#define OFFS_GS      2 +#define OFFS_DS      4 +#define OFFS_DI      6 +#define OFFS_SI      8 +#define OFFS_BP      10 +#define OFFS_SP      12 +#define OFFS_BX      14 +#define OFFS_DX      16 +#define OFFS_CX      18 +#define OFFS_AX      20 +#define OFFS_VECTOR  22 +#define OFFS_IP      24 +#define OFFS_CS      26 +#define OFFS_FLAGS   28 + +#define SEGMENT      0x40 +#define STACK	     0x800  			/* stack at 0x40:0x800 -> 0x800 */ + +.section .bios, "ax" +.code16 +.org 0 + +.globl rm_int00 +rm_int00: +	pushw	$0 +	jmp	any_interrupt16 +.globl rm_int01 +rm_int01: +	pushw	$1 +	jmp	any_interrupt16 +.globl rm_int02 +rm_int02: +	pushw	$2 +	jmp	any_interrupt16 +.globl rm_int03 +rm_int03: +	pushw	$3 +	jmp	any_interrupt16 +.globl rm_int04 +rm_int04: +	pushw	$4 +	jmp	any_interrupt16 +.globl rm_int05 +rm_int05: +	pushw	$5 +	jmp	any_interrupt16 +.globl rm_int06 +rm_int06: +	pushw	$6 +	jmp	any_interrupt16 +.globl rm_int07 +rm_int07: +	pushw	$7 +	jmp	any_interrupt16 +.globl rm_int08 +rm_int08: +	pushw	$8 +	jmp	any_interrupt16 +.globl rm_int09 +rm_int09: +	pushw	$9 +	jmp	any_interrupt16 +.globl rm_int0a +rm_int0a: +	pushw	$10 +	jmp	any_interrupt16 +.globl rm_int0b +rm_int0b: +	pushw	$11 +	jmp	any_interrupt16 +.globl rm_int0c +rm_int0c: +	pushw	$12 +	jmp	any_interrupt16 +.globl rm_int0d +rm_int0d: +	pushw	$13 +	jmp	any_interrupt16 +.globl rm_int0e +rm_int0e: +	pushw	$14 +	jmp	any_interrupt16 +.globl rm_int0f +rm_int0f: +	pushw	$15 +	jmp	any_interrupt16 +.globl rm_int10 +rm_int10: +	pushw	$16 +	jmp	any_interrupt16 +.globl rm_int11 +rm_int11: +	pushw	$17 +	jmp	any_interrupt16 +.globl rm_int12 +rm_int12: +	pushw	$18 +	jmp	any_interrupt16 +.globl rm_int13 +rm_int13: +	pushw	$19 +	jmp	any_interrupt16 +.globl rm_int14 +rm_int14: +	pushw	$20 +	jmp	any_interrupt16 +.globl rm_int15 +rm_int15: +	pushw	$21 +	jmp	any_interrupt16 +.globl rm_int16 +rm_int16: +	pushw	$22 +	jmp	any_interrupt16 +.globl rm_int17 +rm_int17: +	pushw	$23 +	jmp	any_interrupt16 +.globl rm_int18 +rm_int18: +	pushw	$24 +	jmp	any_interrupt16 +.globl rm_int19 +rm_int19: +	pushw	$25 +	jmp	any_interrupt16 +.globl rm_int1a +rm_int1a: +	pushw	$26 +	jmp	any_interrupt16 +.globl rm_int1b +rm_int1b: +	pushw	$27 +	jmp	any_interrupt16 +.globl rm_int1c +rm_int1c: +	pushw	$28 +	jmp	any_interrupt16 +.globl rm_int1d +rm_int1d: +	pushw	$29 +	jmp	any_interrupt16 +.globl rm_int1e +rm_int1e: +	pushw	$30 +	jmp	any_interrupt16 +.globl rm_int1f +rm_int1f: +	pushw	$31 +	jmp	any_interrupt16 +.globl rm_def_int +rm_def_int: +	iret + +  +	/* +	 * All interrupt jumptable entries jump to here +	 * after pushing the interrupt vector number onto the +	 * stack. +	 */ +any_interrupt16: +	pusha					/* save general registers */ +	pushw	%ds				/* save some segments     */ +	pushw	%gs +	pushw	%es +	pushw	%ss				/* save callers stack segment .. */ +	popw	%gs				/* ... in gs */ +	movw	$SEGMENT,%ax			/* setup my segments */ +	movw	%ax,%ds +	movw	%ax,%es +	movw	%ax,%ss +	movw	%sp,%bp +	movw	$STACK,%sp			/* setup BIOS stackpointer */ + +gs	movw	OFFS_VECTOR(%bp), %ax +	cmpw	$0x10, %ax +	je	Lint_10h          +	cmpw	$0x11, %ax +	je	Lint_11h +	cmpw	$0x13, %ax +	je	Lint_13h +	cmpw	$0x15, %ax +	je	Lint_15h +	cmpw	$0x16, %ax +	je	Lint_16h +	movw	$0xffff, %ax +	jmp	Lout +Lint_10h:					/* VGA BIOS services */ +	call	bios_10h +	jmp	Lout +Lint_11h:	 +	call	bios_11h +	jmp	Lout +Lint_13h:					/* BIOS disk services */ +	call	bios_13h +	jmp	Lout +Lint_15h:					/* Misc. BIOS services */ +	call	bios_15h +	jmp	Lout +Lint_16h:					/* keyboard services */ +	call	bios_16h +	jmp	Lout +Lout:	 +	cmpw	$0, %ax +	je	Lhandeled +	 +	/* Insert code for unhandeled INTs here. +	 * +	 * ROLO prints a message to the console  +	 * (we could do that but then we're in 16bit mode +	 * so we'll have to get back into 32bit mode +	 * to use the console I/O routines (if we do this +	 * we shuls make int 0x10 and int 0x16 work as well)) +	 */ +Lhandeled: + +	pushw	%gs				/* restore callers stack segment */ +	popw	%ss +	movw	%bp,%sp				/* restore stackpointer */ + +	popw	%es				/* restore segment selectors */ +	popw	%gs +	popw	%ds +	 +	popa					/* restore GP registers */ +	addw	$2,%sp				/* dump vector number */ +	iret					/* return from interrupt */ + + +/* + ************************************************************ + * BIOS 	interrupt 10h -- VGA services + ************************************************************ + */ +bios_10h: +gs	movw	OFFS_AX(%bp), %ax +	shrw	$8, %ax +	cmpw	$0x3, %ax +	je	Lcur_pos +	cmpw	$0xf, %ax +	je	Lvid_state +	cmpw	$0x12, %ax +	je	Lvid_cfg +	movw	$0xffff, %ax +	ret +Lcur_pos:					/* Read Cursor Position and Size */ +gs	movw	$0, OFFS_CX(%bp) +gs	movw	$0, OFFS_DX(%bp) +	xorw	%ax, %ax +	ret +Lvid_state:					/* Get Video State */ +gs	movw	$(80 << 8|0x03), OFFS_AX(%bp)	/* 80 columns, 80x25, 16 colors */ +gs	movw	$0, OFFS_BX(%bp) +	xorw	%ax, %ax +	ret +Lvid_cfg:	/* Video Subsystem Configuration (EGA/VGA) */ +gs	movw	$0x10, OFFS_BX(%bp)		/* indicate CGA/MDA/HGA */ +	xorw	%ax, %ax +	ret + + +/* + ************************************************************ + * BIOS interrupt 11h -- Equipment determination + ************************************************************ + */ + +bios_11h: +	movw	bios_equipment, %ax +gs	movw	%ax, OFFS_AX(%bp)   +	xorw	%ax, %ax +	ret + + +/* + ************************************************************ + * BIOS interrupt 13h -- Disk services + ************************************************************ + */ +bios_13h: +gs	movw	OFFS_AX(%bp), %ax +	shrw	$8, %ax +	cmpw	$0x15, %ax +	je	Lfunc_15h +	movw	$0xffff, %ax +	ret +Lfunc_15h:	 +gs	movw	OFFS_AX(%bp), %ax +	andw	$0xff, %ax			/* return AH=0->drive not present */ +gs	movw	%ax, OFFS_AX(%bp) +	xorw	%ax, %ax +	ret +	 +	 + +/* + *********************************************************** + * BIOS interrupt 15h -- Miscellaneous services + *********************************************************** + */ +bios_15h: +gs	movw	OFFS_AX(%bp), %ax +	shrw	$8, %ax +	cmpw	$0xc0, %ax +	je	Lfunc_c0h +	cmpw	$0xe8, %ax +	je	Lfunc_e8h +	cmpw	$0x88, %ax +	je	Lfunc_88h +	movw	$0xffff, %ax +	ret + +Lfunc_c0h: 					/* Return System Configuration Parameters (PS2 only) */ +gs	movw	OFFS_FLAGS(%bp), %ax +	orw	$1, %ax				/* return carry -- function not supported */ +gs	movw	%ax, OFFS_FLAGS(%bp) +	xorw	%ax, %ax +	ret +	 +Lfunc_e8h: +gs	movw	OFFS_AX(%bp), %ax +	andw	$0xff, %ax +	cmpw	$1, %ax +	je	Lfunc_e801h +gs	movw	OFFS_FLAGS(%bp), %ax +	orw	$1, %ax				/* return carry -- function not supported */ +gs	movw	%ax, OFFS_FLAGS(%bp) +	xorw	%ax, %ax +	ret +	 +Lfunc_e801h:					/* Get memory size for >64M Configurations */ +	movw	$ram_in_64kb_chunks, %ax +	cmpw	$256, %ax +	ja	Lmore_than_16mb +	shlw	$6, %ax				/* multiply by 64 */	 +gs	movw	%ax, OFFS_AX(%bp)   		/* return memory size in 1kb chunks in AX and CX */ +gs	movw	%ax, OFFS_CX(%bp) +	xorw	%ax, %ax +gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to 0*/ +gs	movw	%ax, OFFS_DX(%bp)	 +gs	movw	OFFS_FLAGS(%bp), %ax +	andw	$0xfffe, %ax			/* clear carry -- function succeeded */ +gs	movw	%ax, OFFS_FLAGS(%bp) +	xorw	%ax, %ax +	ret +	 +Lmore_than_16mb: +	subw	$0x100, %ax			/* subtract 16MB */	 +	 +gs	movw	$0x3c00, OFFS_AX(%bp)		/* return 0x3c00 (16MB-384k) in AX and CX */ +gs	movw	$0x3c00, OFFS_CX(%bp) +gs	movw	%ax, OFFS_BX(%bp)		/* set BX and DX to number of 64kb chunks - 256 */ +gs	movw	%ax, OFFS_DX(%bp)	 + +gs	movw	OFFS_FLAGS(%bp), %ax +	andw	$0xfffe, %ax			/* clear carry -- function succeeded */ +gs	movw	%ax, OFFS_FLAGS(%bp) +	xorw	%ax, %ax +	ret + +Lfunc_88h: +	movw	ram_in_64kb_chunks, %ax +	subw	$16, %ax +	shlw	$6, %ax +	 +gs	movw	%ax, OFFS_AX(%bp)		/* return number of kilobytes in ax */ + +gs	movw	OFFS_FLAGS(%bp), %ax +	andw	$0xfffe, %ax			/* clear carry -- function succeeded */ +gs	movw	%ax, OFFS_FLAGS(%bp) + +	xorw	%ax, %ax +	ret + + +/* + ************************************************************ + * BIOS interrupt 16h -- keyboard services + ************************************************************ + */ +bios_16h: +gs	movw	OFFS_AX(%bp), %ax +	shrw	$8, %ax +	cmpw	$0x03, %ax +	je	Lfunc_03h +	movw	$0xffff, %ax +	ret +Lfunc_03h: +	xorw	%ax, %ax			/* do nothing -- function not supported */ +	ret + + +.globl ram_in_64kb_chunks +ram_in_64kb_chunks: +	.word 	0 + +.globl bios_equipment +bios_equipment: +	.word 	0 + diff --git a/lib_i386/bios_setup.c b/lib_i386/bios_setup.c new file mode 100644 index 000000000..94319afc5 --- /dev/null +++ b/lib_i386/bios_setup.c @@ -0,0 +1,178 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +/* + * Partly based on msbios.c from rolo 1.6: + *---------------------------------------------------------------------- + * (C) Copyright 2000 + * Sysgo Real-Time Solutions GmbH + * Klein-Winternheim, Germany + *---------------------------------------------------------------------- + */ + +#include <common.h> +#include <asm/realmode.h> +#include <asm/io.h> + +#define NUMVECTS	256 + +#define BIOS_DATA        ((char*)0x400) +#define BIOS_DATA_SIZE   256 +#define BIOS_BASE        ((char*)0xf0000) +#define BIOS_CS          0xf000 + +extern u16 ram_in_64kb_chunks; +extern u16 bios_equipment; +extern void *rm_int00; +extern void *rm_int01; +extern void *rm_int02; +extern void *rm_int03; +extern void *rm_int04; +extern void *rm_int05; +extern void *rm_int06; +extern void *rm_int07; +extern void *rm_int08; +extern void *rm_int09; +extern void *rm_int0a; +extern void *rm_int0b; +extern void *rm_int0c; +extern void *rm_int0d; +extern void *rm_int0e; +extern void *rm_int0f; +extern void *rm_int10; +extern void *rm_int11; +extern void *rm_int12; +extern void *rm_int13; +extern void *rm_int14; +extern void *rm_int15; +extern void *rm_int16; +extern void *rm_int17; +extern void *rm_int18; +extern void *rm_int19; +extern void *rm_int1a; +extern void *rm_int1b; +extern void *rm_int1c; +extern void *rm_int1d; +extern void *rm_int1e; +extern void *rm_int1f; +extern void *rm_def_int; + +/* + ************************************************************ + * Install an interrupt vector + ************************************************************ + */ + +static void setvector(int vector, u16 segment, void *handler) +{ +	u16 *ptr = (u16*)(vector*4); +	ptr[0] = ((u32)handler - (segment << 4))&0xffff; +	ptr[1] = segment; +	 +#if 0	 +	printf("setvector: int%02x -> %04x:%04x\n", +	       vector, ptr[1], ptr[0]); +#endif	 +} + +int bios_setup(void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	static int done=0;	 +	int vector; +	 +	if (done) { +		return 0; +	} +	done = 1; +	 +	if (i386boot_bios_size > 65536) { +		printf("BIOS too large (%ld bytes, max is 65536)\n",  +		       i386boot_bios_size); +		return -1; +	} +	 +	memcpy(BIOS_BASE, (void*)i386boot_bios, i386boot_bios_size); + +	/* clear bda */ +	memset(BIOS_DATA, 0, BIOS_DATA_SIZE); +	 +	/* enter some values to the bda */ +	writew(0x3f8, BIOS_DATA);   /* com1 addr */ +	writew(0x2f8, BIOS_DATA+2); /* com2 addr */ +	writew(0x3e8, BIOS_DATA+4); /* com3 addr */ +	writew(0x2e8, BIOS_DATA+6); /* com4 addr */ +	writew(0x278, BIOS_DATA+8); /* lpt1 addr */ +	/* +	 * The kernel wants to read the base memory size +	 * from 40:13. Put a zero there to avoid an error message +	 */ +	writew(0, BIOS_DATA+0x13);  /* base memory size */ + +	 +	/* setup realmode interrupt vectors */	 +	for (vector = 0; vector < NUMVECTS; vector++) { +		setvector(vector, BIOS_CS, &rm_def_int); +	} +	 +	setvector(0x00, BIOS_CS, &rm_int00); +	setvector(0x01, BIOS_CS, &rm_int01); +	setvector(0x02, BIOS_CS, &rm_int02); +	setvector(0x03, BIOS_CS, &rm_int03); +	setvector(0x04, BIOS_CS, &rm_int04); +	setvector(0x05, BIOS_CS, &rm_int05); +	setvector(0x06, BIOS_CS, &rm_int06); +	setvector(0x07, BIOS_CS, &rm_int07); +	setvector(0x08, BIOS_CS, &rm_int08); +	setvector(0x09, BIOS_CS, &rm_int09); +	setvector(0x0a, BIOS_CS, &rm_int0a); +	setvector(0x0b, BIOS_CS, &rm_int0b); +	setvector(0x0c, BIOS_CS, &rm_int0c); +	setvector(0x0d, BIOS_CS, &rm_int0d); +	setvector(0x0e, BIOS_CS, &rm_int0e); +	setvector(0x0f, BIOS_CS, &rm_int0f); +	setvector(0x10, BIOS_CS, &rm_int10); +	setvector(0x11, BIOS_CS, &rm_int11); +	setvector(0x12, BIOS_CS, &rm_int12); +	setvector(0x13, BIOS_CS, &rm_int13); +	setvector(0x14, BIOS_CS, &rm_int14); +	setvector(0x15, BIOS_CS, &rm_int15); +	setvector(0x16, BIOS_CS, &rm_int16); +	setvector(0x17, BIOS_CS, &rm_int17); +	setvector(0x18, BIOS_CS, &rm_int18); +	setvector(0x19, BIOS_CS, &rm_int19); +	setvector(0x1a, BIOS_CS, &rm_int1a); +	setvector(0x1b, BIOS_CS, &rm_int1b); +	setvector(0x1c, BIOS_CS, &rm_int1c); +	setvector(0x1d, BIOS_CS, &rm_int1d); +	setvector(0x1e, BIOS_CS, &rm_int1e); +	setvector(0x1f, BIOS_CS, &rm_int1f); + +	/* fill in data area */ +	ram_in_64kb_chunks = gd->ram_size >> 16; +	bios_equipment = 0; /* FixMe */ +	 +	return 0; +} + diff --git a/lib_i386/board.c b/lib_i386/board.c new file mode 100644 index 000000000..193860a87 --- /dev/null +++ b/lib_i386/board.c @@ -0,0 +1,448 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + *  + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <devices.h> +#include <version.h> +#include <malloc.h> +#include <syscall.h> +#include <net.h> +#include <ide.h> + +extern long _i386boot_start;	     +extern long _i386boot_end;	     +extern long _i386boot_romdata_start; +extern long _i386boot_romdata_dest;  +extern long _i386boot_romdata_size;  +extern long _i386boot_bss_start;    +extern long _i386boot_bss_size;     + +extern long _i386boot_realmode;     +extern long _i386boot_realmode_size; +extern long _i386boot_bios;          +extern long _i386boot_bios_size;     + +/* The symbols defined by the linker script becomes pointers + * which is somewhat inconveient ... */ +ulong i386boot_start         = (ulong)&_i386boot_start;         /* code start (in flash) defined in start.S */ +ulong i386boot_end           = (ulong)&_i386boot_end;	        /* code end (in flash) */ +ulong i386boot_romdata_start = (ulong)&_i386boot_romdata_start; /* datasegment in flash (also code+rodata end) */ +ulong i386boot_romdata_dest  = (ulong)&_i386boot_romdata_dest;  /* data location segment in ram */ +ulong i386boot_romdata_size  = (ulong)&_i386boot_romdata_size;  /* size of data segment */ +ulong i386boot_bss_start     = (ulong)&_i386boot_bss_start;     /* bss start */ +ulong i386boot_bss_size      = (ulong)&_i386boot_bss_size;      /* bss size */ + +ulong i386boot_realmode      = (ulong)&_i386boot_realmode;      /* start of realmode entry code */ +ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; /* size of realmode entry code */ +ulong i386boot_bios          = (ulong)&_i386boot_bios;          /* start of BIOS emulation code */ +ulong i386boot_bios_size     = (ulong)&_i386boot_bios_size;     /* size of BIOS emulation code */ + + +const char version_string[] = +	U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"; + + +/* + * Begin and End of memory area for malloc(), and current "brk" + */ +static ulong mem_malloc_start = 0; +static ulong mem_malloc_end = 0; +static ulong mem_malloc_brk = 0; + +static int mem_malloc_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; +         +#if 1	 +	/* start malloc area right after the stack */ +	mem_malloc_start = i386boot_bss_start +  +		i386boot_bss_size + CFG_STACK_SIZE; +	mem_malloc_start = (mem_malloc_start+3)&~3; +#else +	mem_malloc_start = 0x400000; +#endif	 +#if 1 +	/* Use all available RAM for malloc() */ +	mem_malloc_end = gd->ram_size; +#else	 +	/* Use only  CONFIG_MALLOC_SIZE bytes of RAM for malloc() */ +	mem_malloc_end = mem_malloc_start + CONFIG_MALLOC_SIZE; +#endif	 +	mem_malloc_brk = mem_malloc_start; + +	return 0; +} + +void *sbrk (ptrdiff_t increment) +{ +	ulong old = mem_malloc_brk; +	ulong new = old + increment; + +	if ((new < mem_malloc_start) || (new > mem_malloc_end)) { +		return (NULL); +	} +	mem_malloc_brk = new; + +	return ((void *) old); +} + +char *strmhz (char *buf, long hz) +{ +	long l, n; +	long m; + +	n = hz / 1000000L; +	l = sprintf (buf, "%ld", n); +	m = (hz % 1000000L) / 1000L; +	if (m != 0) +		sprintf (buf + l, ".%03ld", m); +	return (buf); +} + +/************************************************************************ + * Init Utilities							* + ************************************************************************ + * Some of this code should be moved into the core functions, + * or dropped completely, + * but let's get it working (again) first... + */ +static void syscalls_init (void) +{ +	syscall_tbl[SYSCALL_MALLOC] = (void *) malloc; +	syscall_tbl[SYSCALL_FREE] = (void *) free; + +	syscall_tbl[SYSCALL_INSTALL_HDLR] = (void *) irq_install_handler; +	syscall_tbl[SYSCALL_FREE_HDLR] = (void *) irq_free_handler; + +} + +static int init_baudrate (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	uchar tmp[64];	/* long enough for environment variables */ +	int i = getenv_r ("baudrate", tmp, sizeof (tmp)); + +	gd->baudrate = (i > 0) +			? (int) simple_strtoul (tmp, NULL, 10) +			: CONFIG_BAUDRATE; + +	return (0); +} + +static int display_banner (void) +{ + +	printf ("\n\n%s\n\n", version_string); +	printf ("U-Boot code: %08lX -> %08lX  data: %08lX -> %08lX\n" +		"        BSS: %08lX -> %08lX stack: %08lX -> %08lX\n", +		i386boot_start, i386boot_romdata_start-1, +		i386boot_romdata_dest, i386boot_romdata_dest+i386boot_romdata_size-1, +		i386boot_bss_start, i386boot_bss_start+i386boot_bss_size-1, +		i386boot_bss_start+i386boot_bss_size,  +		i386boot_bss_start+i386boot_bss_size+CFG_STACK_SIZE-1); +	 + +	return (0); +} + +/* + * WARNING: this code looks "cleaner" than the PowerPC version, but + * has the disadvantage that you either get nothing, or everything. + * On PowerPC, you might see "DRAM: " before the system hangs - which + * gives a simple yet clear indication which part of the + * initialization if failing. + */ +static int display_dram_config (void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	int i; + +	puts ("DRAM Configuration:\n"); + +	for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) { +		printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); +		print_size (gd->bd->bi_dram[i].size, "\n"); +	} +	 +	return (0); +} + +static void display_flash_config (ulong size) +{ +	puts ("Flash: "); +	print_size (size, "\n"); +} + + + +/* + * Breath some life into the board... + * + * Initialize an SMC for serial comms, and carry out some hardware + * tests. + * + * The first part of initialization is running from Flash memory; + * its main purpose is to initialize the RAM so that we + * can relocate the monitor code to RAM. + */ + +/* + * All attempts to come up with a "common" initialization sequence + * that works for all boards and architectures failed: some of the + * requirements are just _too_ different. To get rid of the resulting + * mess of board dependend #ifdef'ed code we now make the whole + * initialization sequence configurable to the user. + * + * The requirements for any new initalization function is simple: it + * receives a pointer to the "global data" structure as it's only + * argument, and returns an integer return code, where 0 means + * "continue" and != 0 means "fatal error, hang the system". + */ +typedef int (init_fnc_t) (void); + +init_fnc_t *init_sequence[] = { +	cpu_init,		/* basic cpu dependent setup */ +	board_init,		/* basic board dependent setup */ +	dram_init,		/* configure available RAM banks */ +	mem_malloc_init,        /* dependant on dram_init */ +	interrupt_init,		/* set up exceptions */ +	timer_init,	 +	env_init,		/* initialize environment */ +	init_baudrate,		/* initialze baudrate settings */ +	serial_init,		/* serial communications setup */ +	display_banner, +	display_dram_config, + +	NULL, +}; + +gd_t *global_data; + +void start_i386boot (void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	char *s; +	int i; +	ulong size; +	static gd_t gd_data; +	static bd_t bd_data; +	init_fnc_t **init_fnc_ptr; +	 +	show_boot_progress(0x21); + +	gd = global_data = &gd_data; +	 +	memset (gd, 0, sizeof (gd_t)); +	gd->bd = &bd_data; +	memset (gd->bd, 0, sizeof (bd_t)); +	show_boot_progress(0x22); + +	 +	for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) { +		show_boot_progress(0xa130|i); + +		if ((*init_fnc_ptr)() != 0) { +			hang (); +		} +	} +	show_boot_progress(0x23); + +	/* configure available FLASH banks */ +	size = flash_init(); +	display_flash_config(size); +	show_boot_progress(0x24); + +	show_boot_progress(0x25); + +	/* initialize environment */ +	env_relocate (); +	show_boot_progress(0x26); + + +	/* IP Address */ +	bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr"); + +	/* MAC Address */ +	{ +		int i; +		ulong reg; +		char *s, *e; +		uchar tmp[64]; + +		i = getenv_r ("ethaddr", tmp, sizeof (tmp)); +		s = (i > 0) ? tmp : NULL; + +		for (reg = 0; reg < 6; ++reg) { +			bd_data.bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0; +			if (s) +				s = (*e) ? e + 1 : e; +		} +	} + +#if defined(CONFIG_PCI) +	/* +	 * Do pci configuration +	 */ +	pci_init(); +#endif + +	show_boot_progress(0x27); + + +	devices_init (); + +	/* allocate syscalls table (console_init_r will fill it in */ +	syscall_tbl = (void **) malloc (NR_SYSCALLS * sizeof (void *)); + +	/* Initialize the console (after the relocation and devices init) */ +	console_init_r(); +	syscalls_init(); + +#ifdef CONFIG_MISC_INIT_R +	/* miscellaneous platform dependent initialisations */ +	misc_init_r(); +#endif + + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && (0) +	WATCHDOG_RESET(); +# ifdef DEBUG +	puts ("Reset Ethernet PHY\n"); +# endif +	reset_phy(); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) && !(CONFIG_COMMANDS & CFG_CMD_IDE) +	WATCHDOG_RESET(); +	puts ("PCMCIA:"); +	pcmcia_init(); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +	WATCHDOG_RESET(); +	puts("KGDB:  "); +	kgdb_init(); +#endif + +	/* enable exceptions */ +	enable_interrupts (); +	show_boot_progress(0x28); + +	/* Must happen after interrupts are initialized since +	 * an irq handler gets installed +	 */ +#ifdef CONFIG_SERIAL_SOFTWARE_FIFO +	serial_buffered_init(); +#endif +     +#ifdef CONFIG_STATUS_LED +	status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING); +#endif + +	udelay (20); + +	set_timer (0); + +	/* Initialize from environment */ +	if ((s = getenv ("loadaddr")) != NULL) { +		load_addr = simple_strtoul (s, NULL, 16); +	} +#if (CONFIG_COMMANDS & CFG_CMD_NET) +	if ((s = getenv ("bootfile")) != NULL) { +		copy_filename (BootFile, s, sizeof (BootFile)); +	} +#endif /* CFG_CMD_NET */ + +	WATCHDOG_RESET(); + +#if (CONFIG_COMMANDS & CFG_CMD_IDE) +	WATCHDOG_RESET(); +	puts("IDE:   "); +	ide_init(); +#endif /* CFG_CMD_IDE */ + +#if (CONFIG_COMMANDS & CFG_CMD_SCSI) +	WATCHDOG_RESET(); +	puts("SCSI:  "); +	scsi_init(); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_DOC) +	WATCHDOG_RESET(); +	puts ("DOC:   "); +	doc_init(); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) +	WATCHDOG_RESET(); +	puts("Net:   "); +	eth_initialize(gd->bd); +#endif + +#ifdef CONFIG_LAST_STAGE_INIT +	WATCHDOG_RESET(); +	/* +	 * Some parts can be only initialized if all others (like +	 * Interrupts) are up and running (i.e. the PC-style ISA +	 * keyboard). +	 */ +	last_stage_init(); +#endif + + + +#ifdef CONFIG_POST +	post_run (NULL, POST_RAM | post_bootmode_get(0)); +	if (post_bootmode_get(0) & POST_POWERFAIL) { +		post_bootmode_clear(); +		board_poweroff(); +	} +#endif + +	show_boot_progress(0x29); +	 +	/* main_loop() can return to retry autoboot, if so just run it again. */ +	for (;;) { +		main_loop (); +	} + +	/* NOTREACHED - no way out of command loop except booting */ +} + +void hang (void) +{ +	puts ("### ERROR ### Please RESET the board ###\n"); +	for (;;); +} + + diff --git a/lib_i386/i386_linux.c b/lib_i386/i386_linux.c new file mode 100644 index 000000000..c37a0d8ee --- /dev/null +++ b/lib_i386/i386_linux.c @@ -0,0 +1,174 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include <common.h> +#include <command.h> +#include <cmd_boot.h> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> +#include <asm/zimage.h> + + +extern image_header_t header;           /* from cmd_bootm.c */ + + +image_header_t *fake_header(image_header_t *hdr, void *ptr, int size) +{ +	/* try each supported image type in order */ +	if (NULL != fake_zimage_header(hdr, ptr, size)) { +		return hdr; +	} +	 +	return NULL; +} + + +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], +		ulong addr, ulong *len_ptr, int   verify) +{ +	ulong base_ptr; +	 +	ulong len = 0, checksum; +	ulong initrd_start, initrd_end; +	ulong data; +	image_header_t *hdr = &header; +	 +	/* +	 * Check if there is an initrd image +	 */ +	if (argc >= 3) { +		addr = simple_strtoul(argv[2], NULL, 16); +		 +		printf ("## Loading Ramdisk Image at %08lx ...\n", addr); +		 +		/* Copy header so we can blank CRC field for re-calculation */ +		memcpy (&header, (char *)addr, sizeof(image_header_t)); +		 +		if (ntohl(hdr->ih_magic) != IH_MAGIC) { +			printf ("Bad Magic Number\n"); +			do_reset (cmdtp, flag, argc, argv); +		} +		 +		data = (ulong)&header; +		len  = sizeof(image_header_t); +		 +		checksum = ntohl(hdr->ih_hcrc); +		hdr->ih_hcrc = 0; +		 +		if (crc32 (0, (char *)data, len) != checksum) { +			printf ("Bad Header Checksum\n"); +			do_reset (cmdtp, flag, argc, argv); +		} +		 +		print_image_hdr (hdr); +		 +		data = addr + sizeof(image_header_t); +		len  = ntohl(hdr->ih_size); +		 +		if (verify) { +			ulong csum = 0; +			 +			printf ("   Verifying Checksum ... "); +			csum = crc32 (0, (char *)data, len); +			if (csum != ntohl(hdr->ih_dcrc)) { +				printf ("Bad Data CRC\n"); +				do_reset (cmdtp, flag, argc, argv); +			} +			printf ("OK\n"); +		} +		 +		if ((hdr->ih_os   != IH_OS_LINUX)	|| +		    (hdr->ih_arch != IH_CPU_I386)	|| +		    (hdr->ih_type != IH_TYPE_RAMDISK)	) { +			printf ("No Linux i386 Ramdisk Image\n"); +			do_reset (cmdtp, flag, argc, argv); +		} +		 +		/* +		 * Now check if we have a multifile image +		 */ +	} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { +		ulong tail    = ntohl(len_ptr[0]) % 4; +		int i; +		 +		/* skip kernel length and terminator */ +		data = (ulong)(&len_ptr[2]); +		/* skip any additional image length fields */ +		for (i=1; len_ptr[i]; ++i) +			data += 4; +		/* add kernel length, and align */ +		data += ntohl(len_ptr[0]); +		if (tail) { +			data += 4 - tail; +		} +		 +		len   = ntohl(len_ptr[1]); +		 +	} else { +		/* +		 * no initrd image +		 */ +		data = 0; +	} +	 +#ifdef	DEBUG +	if (!data) { +		printf ("No initrd\n"); +	} +#endif +	 +	if (data) { +		initrd_start = data; +		initrd_end   = initrd_start + len; +		printf ("   Loading Ramdisk to %08lx, end %08lx ... ", +			initrd_start, initrd_end); +		memmove ((void *)initrd_start, (void *)data, len); +		printf ("OK\n"); +	} else { +		initrd_start = 0; +		initrd_end = 0; +	} +	 +	base_ptr = load_zimage(addr + sizeof(image_header_t), ntohl(hdr->ih_size),  +			       initrd_start, initrd_end-initrd_start, 0); + +	if (NULL == base_ptr) { +		printf ("## Kernel loading failed ...\n"); +		do_reset(cmdtp, flag, argc, argv); +		 +	} +		 +#ifdef DEBUG +	printf ("## Transferring control to Linux (at address %08x) ...\n", +		(u32)base_ptr); +#endif +		 +	/* we assume that the kernel is in place */ +	printf("\nStarting kernel ...\n\n"); +		 +	boot_zimage(base_ptr); +	 +} + + diff --git a/lib_i386/ic/ali512x.c b/lib_i386/ic/ali512x.c new file mode 100644 index 000000000..4537095db --- /dev/null +++ b/lib_i386/ic/ali512x.c @@ -0,0 +1,442 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Based on sc520cdp.c from rolo 1.6: + *---------------------------------------------------------------------- + * (C) Copyright 2000 + * Sysgo Real-Time Solutions GmbH + * Klein-Winternheim, Germany + *---------------------------------------------------------------------- + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/ic/ali512x.h> + + +/* ALI M5123 Logical device numbers: + * 0 FDC + * 1 unused? + * 2 unused? + * 3 lpt + * 4 UART1 + * 5 UART2 + * 6 RTC + * 7 mouse/kbd + * 8 CIO + */ + +/* + ************************************************************ + *  Some access primitives for the ALi chip:                * + ************************************************************ + */ + +static void ali_write(u8 index, u8 value) +{	 +	/* write an arbirary register */ +	outb(index, ALI_INDEX); +	outb(value, ALI_DATA); +} + +static int ali_read(u8 index) +{ +	outb(index, ALI_INDEX); +	return inb(ALI_DATA); +} + +#define ALI_OPEN() \ +	outb(0x51, ALI_DATA); \ +	outb(0x23, ALI_DATA)	 + + +#define ALI_CLOSE() \ +	outb(0xbb, ALI_DATA) + +/* Select a logical device */ +#define ALI_SELDEV(dev)	\ +	ali_write(0x07, dev)	 + + +void ali512x_init(void) +{ +	ALI_OPEN(); + +	ali_write(0x02, 0x01);	/* soft reset */ +	ali_write(0x03, 0x03);	/* disable access to CIOs */ +	ali_write(0x22, 0x00);	/* disable direct powerdown */ +	ali_write(0x23, 0x00);	/* disable auto powerdown */ +	ali_write(0x24, 0x00);	/* IR 8 is active hi, pin26 is PDIR */ + +	ALI_CLOSE(); +} + +void ali512x_set_fdc(int enabled, u16 io, u8 irq, u8 dma_channel) +{ +	ALI_OPEN(); +	ALI_SELDEV(0); +	 +	ali_write(0x30, enabled?1:0); +	if (enabled) { +		ali_write(0x60, io >> 8); +		ali_write(0x61, io & 0xff); +		ali_write(0x70, irq); +		ali_write(0x74, dma_channel); +		 +		/* AT mode, no drive swap */ +		ali_write(0xf0, 0x08); +		ali_write(0xf1, 0x00); +		ali_write(0xf2, 0xff); +		ali_write(0xf4, 0x00); +	} +	ALI_CLOSE(); +} + + +void ali512x_set_pp(int enabled, u16 io, u8 irq, u8 dma_channel) +{ +	ALI_OPEN(); +	ALI_SELDEV(3); +	 +	ali_write(0x30, enabled?1:0); +	if (enabled) { +		ali_write(0x60, io >> 8); +		ali_write(0x61, io & 0xff); +		ali_write(0x70, irq); +		ali_write(0x74, dma_channel); +		 +		/* mode: EPP 1.9, ECP FIFO threshold = 7, IRQ active low */ +		ali_write(0xf0, 0xbc); +		/* 12 MHz, Burst DMA in ECP */ +		ali_write(0xf1, 0x05); +	} +	ALI_CLOSE(); + +} + +void ali512x_set_uart(int enabled, int index, u16 io, u8 irq) +{ +	ALI_OPEN(); +	ALI_SELDEV(index?5:4); +	 +	ali_write(0x30, enabled?1:0); +	if (enabled) { +		ali_write(0x60, io >> 8); +		ali_write(0x61, io & 0xff); +		ali_write(0x70, irq); +		 +		ali_write(0xf0, 0x00); +		ali_write(0xf1, 0x00); +		 +		/* huh? write 0xf2 twice - a typo in rolo +		 * or some secret ali errata? Who knows?  +		 */ +		if (index) { +			ali_write(0xf2, 0x00); +		} +		ali_write(0xf2, 0x0c); +	} +	ALI_CLOSE(); + +} + +void ali512x_set_uart2_irda(int enabled) +{ +	ALI_OPEN(); +	ALI_SELDEV(5); +	 +	ali_write(0xf1, enabled?0x48:0x00); /* fullduplex IrDa */ +	ALI_CLOSE(); + +} + +void ali512x_set_rtc(int enabled, u16 io, u8 irq) +{ +	ALI_OPEN(); +	ALI_SELDEV(6); +	 +	ali_write(0x30, enabled?1:0); +	if (enabled) { +		ali_write(0x60, io >> 8); +		ali_write(0x61, io & 0xff); +		ali_write(0x70, irq); + +		ali_write(0xf0, 0x00); +	} +	ALI_CLOSE(); +} + +void ali512x_set_kbc(int enabled, u8 kbc_irq, u8 mouse_irq) +{ +	ALI_OPEN(); +	ALI_SELDEV(7); +	 +	ali_write(0x30, enabled?1:0); +	if (enabled) { +		ali_write(0x70, kbc_irq); +		ali_write(0x72, mouse_irq);		 +		 +		ali_write(0xf0, 0x00); +	} +	ALI_CLOSE(); +} + + +/* Common I/O + *  + * (This descripotsion is base on several incompete sources + *  since I have not been able to obtain any datasheet for the device + *  there may be some mis-understandings burried in here.  + *  -- Daniel daniel@omicron.se) + *  + * There are 22 CIO pins numbered + * 10-17 + * 20-25 + * 30-37 + *  + * 20-24 are dedicated CIO pins, the other 17 are muliplexed with + * other functions. + *  + *           Secondary  + * CIO Pin   Function    Decription + * ======================================================= + * CIO10     IRQIN1      Interrupt input 1? + * CIO11     IRQIN2      Interrupt input 2? + * CIO12     IRRX        IrDa Receive + * CIO13     IRTX        IrDa Transmit + * CIO14     P21         KBC P21 fucntion + * CIO15     P20         KBC P21 fucntion + * CIO16     I2C_CLK     I2C Clock + * CIO17     I2C_DAT     I2C Data + *  + * CIO20     - + * CIO21     - + * CIO22     - + * CIO23     - + * CIO24     - + * CIO25     LOCK        Keylock + *  + * CIO30     KBC_CLK     Keybaord Clock + * CIO31     CS0J        General Chip Select decoder CS0J + * CIO32     CS1J        General Chip Select decoder CS1J + * CIO33     ALT_KCLK    Alternative Keyboard Clock + * CIO34     ALT_KDAT    Alternative Keyboard Data + * CIO35     ALT_MCLK    Alternative Mouse Clock + * CIO36     ALT_MDAT    Alternative Mouse Data + * CIO37     ALT_KBC     Alternative KBC select + * + * The CIO use a double indirect address scheme.  + *  + * Reigster 3 in the SIO is used to selectg where the CIO  + * I/O registers show up under function 8. Note that these + * registers clash with the CIO function select regsters, + * below. + *  + * SIO reigster 3 (CIO Address Selection) bit definitions: + * bit 7   CIO data register enabled + * bit 1-0 CIO indirect registers select + *     	 0  index = 0xE0 data = 0xE1 + *       1  index = 0xE2 data = 0xE3 + *       2  index = 0xE4 data = 0xE5 + *       3  index = 0xEA data = 0xEB + *  + * There are three CIO I/O register accessed via CIO index and CIO data + * 0x01     CIO 10-17 data + * 0x02     CIO 20-25 data (bits 7-6 unused) + * 0x03     CIO 30-37 data + *  + *  + * The pin function is accessed through normal  + * SIO registers, each register have the same format: + *  + * Bit   Function                     Value + * 0     Input/output                 1=input  + * 1     Polarity of signal           1=inverted + * 2     Unused                       ?? + * 3     Function (normal or special) 1=special + * 7-4   Unused + *  + * SIO REG + * 0xe0     CIO 10 Config + * 0xe1     CIO 11 Config + * 0xe2     CIO 12 Config + * 0xe3     CIO 13 Config + * 0xe4     CIO 14 Config + * 0xe5     CIO 15 Config + * 0xe6     CIO 16 Config + * 0xe7     CIO 16 Config + * + * 0xe8     CIO 20 Config + * 0xe9     CIO 21 Config + * 0xea     CIO 22 Config + * 0xeb     CIO 23 Config + * 0xec     CIO 24 Config + * 0xed     CIO 25 Config + * + * 0xf5     CIO 30 Config + * 0xf6     CIO 31 Config + * 0xf7     CIO 32 Config + * 0xf8     CIO 33 Config + * 0xf9     CIO 34 Config + * 0xfa     CIO 35 Config + * 0xfb     CIO 36 Config + * 0xfc     CIO 37 Config + *  + */ + +void ali512x_set_cio(int enabled) +{ +	int i; +	 +	ALI_OPEN(); +	ali_write(0x3, 3);    /* Disable CIO data register */ +	 +	ALI_SELDEV(8); +	ali_write(0x30, enabled?1:0); +	 +	/* set all pins to input to start with */ +	for (i=0xe0;i<0xee;i++) { +		ali_write(i, 1); +	} +	for (i=0xf5;i<0xfe;i++) { +		ali_write(i, 1); +	} +			 +	ALI_CLOSE(); +} + +void ali512x_cio_function(int pin, int special, int inv, int input) +{ +	u8 data; +	u8 addr; +	 +	 +	/* valid pins are 10-17, 20-25 and 30-37 */ +	if (pin >= 10 && pin <= 17) {  +		addr = 0xe0+(pin-10); +	} else if (pin >= 20 && pin <= 25) { +		addr = 0xe8+(pin-20); +	} else if (pin >= 30 && pin <= 37) {  +		addr = 0xf5+(pin-30); +	} else { +		return; +	} +	 +	ALI_OPEN(); +	ALI_SELDEV(8); +	 +	ali_write(0x03, 0x03);    /* Disable CIO data register */ +	 +	data=0; +	if (special) { +		data |= 0x08; +	} else { +		if (inv) { +			data |= 0x02; +		} +		if (input) { +			data |= 0x01; +		} +	} +	 +	ali_write(addr, data); +	 +	ALI_CLOSE(); +} + +void ali512x_cio_out(int pin, int value)  +{ +	u8 reg; +	u8 data; +	u8 bit; +	 +	/* valid pins are 10-17, 20-25 and 30-37 */ +	if (pin >= 10 && pin <= 17) {  +		reg = 1; +		pin -= 10; +	} else if (pin >= 20 && pin <= 25) { +		reg = 2; +		pin -= 20; +	} else if (pin >= 30 && pin <= 37) {  +		reg = 3; +		pin -= 30; +	} else { +		return; +	} +	bit = 1 << pin; +	 +	ALI_OPEN(); +	ALI_SELDEV(8); +	 +	ali_write(0x03, 0x83);    /* Enable CIO data register, use data port at 0xea */ +	 +	ali_write(0xea, reg);     /* select I/O register */ +	data = ali_read(0xeb); +	if (value) { +		data |= bit; +	} else { +		data &= ~bit; +	} +	ali_write(0xeb, data); +	ali_write(0xea, 0);       /* select register 0 */ +	ali_write(0x03, 0x03);    /* Disable CIO data register */ +	ALI_CLOSE(); +} + +int ali512x_cio_in(int pin) +{ +	u8 reg; +	u8 data; +	u8 bit; +	 +	/* valid pins are 10-17, 20-25 and 30-37 */ +	if (pin >= 10 && pin <= 17) {  +		reg = 1; +		pin -= 10; +	} else if (pin >= 20 && pin <= 25) { +		reg = 2; +		pin -= 20; +	} else if (pin >= 30 && pin <= 37) {  +		reg = 3; +		pin -= 30; +	} else { +		return -1;  +	} +	bit = 1 << pin; +	 +	ALI_OPEN(); +	ALI_SELDEV(8); +	 +	ali_write(0x03, 0x83);    /* Enable CIO data register, use data port at 0xea */ +	 +	ali_write(0xea, reg);     /* select I/O register */ +	data = ali_read(0xeb); +	ali_write(0xea, 0);       /* select register 0 */ +	ali_write(0x03, 0x03);    /* Disable CIO data register */ +	ALI_CLOSE(); +	 +	return data & bit;  +} + +  diff --git a/lib_i386/ic/sc520.c b/lib_i386/ic/sc520.c new file mode 100644 index 000000000..d202625bb --- /dev/null +++ b/lib_i386/ic/sc520.c @@ -0,0 +1,348 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* stuff specific for the sc520, + * but idependent of implementation */ + + +#include <common.h> +#include <config.h> +#include <pci.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/ic/sc520.h> + +/*  + * utility functions for boards based on the AMD sc520  + *  + * void write_mmcr_byte(u16 mmcr, u8 data) + * void write_mmcr_word(u16 mmcr, u16 data) + * void write_mmcr_long(u16 mmcr, u32 data) + *  + * u8   read_mmcr_byte(u16 mmcr) + * u16  read_mmcr_word(u16 mmcr) + * u32  read_mmcr_long(u16 mmcr) + *  + * void init_sc520(void) + * unsigned long init_sc520_dram(void) + * void pci_sc520_init(struct pci_controller *hose) + *  + * void reset_timer(void) + * ulong get_timer(ulong base) + * void set_timer(ulong t) + * void udelay(unsigned long usec) + *  + */ + +static u32 mmcr_base= 0xfffef000; + +void write_mmcr_byte(u16 mmcr, u8 data) +{ +	writeb(data, mmcr+mmcr_base); +} + +void write_mmcr_word(u16 mmcr, u16 data) +{ +	writew(data, mmcr+mmcr_base);	 +} + +void write_mmcr_long(u16 mmcr, u32 data) +{ +	writel(data, mmcr+mmcr_base); +} + +u8 read_mmcr_byte(u16 mmcr) +{ +	return readb(mmcr+mmcr_base); +} + +u16 read_mmcr_word(u16 mmcr) +{ +	return readw(mmcr+mmcr_base);	 +} + +u32 read_mmcr_long(u16 mmcr) +{ +	return readl(mmcr+mmcr_base); +} + + +void init_sc520(void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	 +	/* Set the UARTxCTL register at it's slower, +	 * baud clock giving us a 1.8432 MHz reference  +	 */ +	write_mmcr_byte(SC520_UART1CTL, 7); +	write_mmcr_byte(SC520_UART2CTL, 7); +	 +	/* first set the timer pin mapping */ +	write_mmcr_byte(SC520_CLKSEL, 0x72);	/* no clock frequency selected, use 1.1892MHz */ +	 +	/* enable PCI bus arbitrer */ +	write_mmcr_byte(SC520_SYSARBCTL,0x02);  /* enable concurrent mode */ +	 +	write_mmcr_word(SC520_SYSARBMENB,0x1f); /* enable external grants */ +	write_mmcr_word(SC520_HBCTL,0x04);      /* enable posted-writes */ + + +	if (CFG_SC520_HIGH_SPEED) { +		write_mmcr_byte(SC520_CPUCTL, 0x2);	/* set it to 133 MHz and write back */ +		gd->cpu_clk = 133000000; +		printf("## CPU Speed set to 133MHz\n"); +	} else { +		write_mmcr_byte(SC520_CPUCTL, 1);	/* set CPU to 100 MHz and write back cache */ +		printf("## CPU Speed set to 100MHz\n"); +		gd->cpu_clk = 100000000; +	} +	 + +	/* wait at least one millisecond */ +        asm("movl	$0x2000,%%ecx\n" +	    "wait_loop:	pushl %%ecx\n" +	    "popl	%%ecx\n" +	    "loop wait_loop\n": : : "ecx"); + +	/* turn on the SDRAM write buffer */ +	write_mmcr_byte(SC520_DBCTL, 0x11); + +	/* turn on the cache and disable write through */ +	asm("movl	%%cr0, %%eax\n" +	    "andl	$0x9fffffff, %%eax\n" +	    "movl	%%eax, %%cr0\n"  : : : "eax"); +} + +unsigned long init_sc520_dram(void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	bd_t *bd = gd->bd; +	 +	u32 dram_present=0; +	u32 dram_ctrl; + +	int val; +	 +	int cas_precharge_delay = CFG_SDRAM_PRECHARGE_DELAY;	 +	int refresh_rate        = CFG_SDRAM_REFRESH_RATE;	 +	int ras_cas_delay       = CFG_SDRAM_RAS_CAS_DELAY; +	 +	/* set SDRAM speed here */ +	 +	refresh_rate/=78;	 +	if (refresh_rate<=1) { +		val = 0;  /* 7.8us */ +	} else if (refresh_rate==2) { +		val = 1;  /* 15.6us */ +	} else if (refresh_rate==3 || refresh_rate==4) { +		val = 2;  /* 31.2us */ +	} else { +		val = 3;  /* 62.4us */ +	} +	write_mmcr_byte(SC520_DRCCTL, (read_mmcr_byte(SC520_DRCCTL) & 0xcf) | (val<<4)); +	 +	val = read_mmcr_byte(SC520_DRCTMCTL); +	val &= 0xf0; +	 +	if (cas_precharge_delay==3) {		 +		val |= 0x04;   /* 3T */ +	} else if (cas_precharge_delay==4) {		 +		val |= 0x08;   /* 4T */ +	} else if (cas_precharge_delay>4) {		 +		val |= 0x0c; +	}  +	 +	if (ras_cas_delay > 3) { +		val |= 2;  +	} else { +		val |= 1;  +	} +	write_mmcr_byte(SC520_DRCTMCTL, val); + + +	/* We read-back the configuration of the dram +	 * controller that the assembly code wrote */ +	dram_ctrl = read_mmcr_long(SC520_DRCBENDADR); +	 + +	bd->bi_dram[0].start = 0; +	if (dram_ctrl & 0x80) { +		/* bank 0 enabled */ +		dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22; +		bd->bi_dram[0].size = bd->bi_dram[1].start;  + +	} else { +		bd->bi_dram[0].size = 0; +		bd->bi_dram[1].start = bd->bi_dram[0].start; +	} +	 +	if (dram_ctrl & 0x8000) { +		/* bank 1 enabled */ +		dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14; +		bd->bi_dram[1].size = bd->bi_dram[2].start -  bd->bi_dram[1].start;  +	} else { +		bd->bi_dram[1].size = 0; +		bd->bi_dram[2].start = bd->bi_dram[1].start; +	} +	 +	if (dram_ctrl & 0x800000) { +		/* bank 2 enabled */ +		dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6; +		bd->bi_dram[2].size = bd->bi_dram[3].start -  bd->bi_dram[2].start;  +	} else { +		bd->bi_dram[2].size = 0; +		bd->bi_dram[3].start = bd->bi_dram[2].start; +	}  +	 +	if (dram_ctrl & 0x80000000) { +		/* bank 3 enabled */ +		dram_present  = (dram_ctrl & 0x7f000000) >> 2; +		bd->bi_dram[3].size = dram_present -  bd->bi_dram[3].start; +	} else { +		bd->bi_dram[3].size = 0; +	} + +	 +#if 0	 +	printf("Configured %d bytes of dram\n", dram_present); +#endif	 +	gd->ram_size = dram_present; +	 +	return dram_present; +} + + +#ifdef CONFIG_PCI + + + +void pci_sc520_init(struct pci_controller *hose) +{ +	hose->first_busno = 0; +	hose->last_busno = 0xff; + +	/* System memory space */ +	pci_set_region(hose->regions + 0,  +		       SC520_PCI_MEMORY_BUS, +		       SC520_PCI_MEMORY_PHYS, +		       SC520_PCI_MEMORY_SIZE, +		       PCI_REGION_MEM | PCI_REGION_MEMORY); + +	/* PCI memory space */ +	pci_set_region(hose->regions + 1,  +		       SC520_PCI_MEM_BUS, +		       SC520_PCI_MEM_PHYS, +		       SC520_PCI_MEM_SIZE, +		       PCI_REGION_MEM); + +	/* ISA/PCI memory space */ +	pci_set_region(hose->regions + 2,  +		       SC520_ISA_MEM_BUS, +		       SC520_ISA_MEM_PHYS, +		       SC520_ISA_MEM_SIZE, +		       PCI_REGION_MEM); + +	/* PCI I/O space */ +	pci_set_region(hose->regions + 3,  +		       SC520_PCI_IO_BUS, +		       SC520_PCI_IO_PHYS, +		       SC520_PCI_IO_SIZE, +		       PCI_REGION_IO); + +	/* ISA/PCI I/O space */ +	pci_set_region(hose->regions + 4,  +		       SC520_ISA_IO_BUS, +		       SC520_ISA_IO_PHYS, +		       SC520_ISA_IO_SIZE, +		       PCI_REGION_IO); + +	hose->region_count = 5; + +	pci_setup_type1(hose, +			SC520_REG_ADDR, +			SC520_REG_DATA); + +	pci_register_hose(hose); + +	hose->last_busno = pci_hose_scan(hose); +	 +	/* enable target memory acceses on host brige */ +	pci_write_config_word(0, PCI_COMMAND,  +			      PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + +} + + +#endif + +#ifdef CFG_TIMER_SC520 + + +void reset_timer(void) +{ +	write_mmcr_word(SC520_GPTMR0CNT, 0); +	write_mmcr_word(SC520_GPTMR0CTL, 0x6001); +	 +} + +ulong get_timer(ulong base) +{ +	/* fixme: 30 or 33 */ +	return 	read_mmcr_word(SC520_GPTMR0CNT) / 33; +} + +void set_timer(ulong t) +{ +	/* FixMe: use two cascade coupled timers */ +	write_mmcr_word(SC520_GPTMR0CTL, 0x4001); +	write_mmcr_word(SC520_GPTMR0CNT, t*33); +	write_mmcr_word(SC520_GPTMR0CTL, 0x6001); +} + + +void udelay(unsigned long usec) +{ +	int m=0; +	long u; +	 +	read_mmcr_word(SC520_SWTMRMILLI); +	read_mmcr_word(SC520_SWTMRMICRO); +	      +#if 0 +	/* do not enable this line, udelay is used in the serial driver -> recursion */ +	printf("udelay: %ld m.u %d.%d  tm.tu %d.%d\n", usec, m, u, tm, tu); +#endif	 +	while (1) { +		 +		m += read_mmcr_word(SC520_SWTMRMILLI); +		u = read_mmcr_word(SC520_SWTMRMICRO) + (m * 1000); +		 +		if (usec <= u) { +			break; +		} +	} +} + +#endif + + diff --git a/lib_i386/ic/sc520_asm.S b/lib_i386/ic/sc520_asm.S new file mode 100644 index 000000000..72110c4a0 --- /dev/null +++ b/lib_i386/ic/sc520_asm.S @@ -0,0 +1,530 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* This file is largely based on code obtned from AMD. AMD's original + * copyright is included below  + */ + +/* + *  ============================================================================= + *                                                                               + *   Copyright 1999 Advanced Micro Devices, Inc.                                 + *                                                                               + *  This software is the property of Advanced Micro Devices, Inc  (AMD)  which  + *  specifically grants the user the right to modify, use and distribute this  + *  software provided this COPYRIGHT NOTICE is not removed or altered.  All  + *  other rights are reserved by AMD.                                                        + *                                                                              + *  THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY  + *  OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF  + *  THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE. + *  IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER + *  (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + *  INTERRUPTION, LOSS OF INFORMAITON) ARISING OUT OF THE USE OF OR INABILITY + *  TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF + *  SUCH DAMAGES.  BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR + *  LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE + *  LIMITATION MAY NOT APPLY TO YOU. + *  + *  AMD does not assume any responsibility for any errors that may appear in + *  the Materials nor any responsibility to support or update the Materials. + *  AMD retains the right to make changes to its test specifications at any + *  time, without notice. + *  + *  So that all may benefit from your experience, please report  any  problems  + *  or suggestions about this software back to AMD.  Please include your name,  + *  company,  telephone number,  AMD product requiring support and question or  + *  problem encountered.                                                        + *                                                                              + *  Advanced Micro Devices, Inc.         Worldwide support and contact            + *  Embedded Processor Division            information available at:                + *  Systems Engineering                       epd.support@amd.com + *  5204 E. Ben White Blvd.                          -or- + *  Austin, TX 78741                http://www.amd.com/html/support/techsup.html + *  ============================================================================ + */ + + +/******************************************************************************* + *	 AUTHOR      : Buddy Fey - Original.  + ******************************************************************************* + */ + + +/******************************************************************************* + *       FUNCTIONAL DESCRIPTION: + * This routine is called to autodetect the geometry of the DRAM. + * + * This routine is called to determine the number of column bits for the DRAM + * devices in this external bank. This routine assumes that the external bank + * has been configured for an 11-bit column and for 4 internal banks. This gives + * us the maximum address reach in memory. By writing a test value to the max + * address and locating where it aliases to, we can determine the number of valid + * column bits. + * + * This routine is called to determine the number of internal banks each DRAM + * device has. The external bank (under test) is configured for maximum reach + * with 11-bit columns and 4 internal banks. This routine will write to a max + * address (BA1 and BA0 = 1) and then read from an address with BA1=0 to see if + * that column is a "don't care". If BA1 does not affect write/read of data, + * then this device has only 2 internal banks. + * + * This routine is called to determine the ending address for this external + * bank of SDRAM. We write to a max address with a data value and then disable + * row address bits looking for "don't care" locations. Each "don't care" bit + * represents a dividing of the maximum density (128M) by 2. By dividing the + * maximum of 32 4M chunks in an external bank down by all the "don't care" bits + * determined during sizing, we set the proper density. + * + * WARNINGS. + * bp must be preserved because it is used for return linkage. + * + * EXIT + * nothing returned - but the memory subsystem is enabled + ******************************************************************************* + */ + +.section .text +.equ            DRCCTL,     0x0fffef010   /* DRAM control register */ +.equ            DRCTMCTL,   0x0fffef012   /* DRAM timing control register */ +.equ            DRCCFG,     0x0fffef014   /* DRAM bank configuration register */ +.equ            DRCBENDADR, 0x0fffef018   /* DRAM bank ending address register */ +.equ            ECCCTL,     0x0fffef020   /* DRAM ECC control register */ +.equ            DBCTL,      0x0fffef040   /* DRAM buffer control register */ + +.equ            CACHELINESZ, 0x00000010   /* size of our cache line (read buffer) */ +.equ            COL11_ADR,  0x0e001e00    /* 11 col addrs */ +.equ            COL10_ADR,  0x0e000e00    /* 10 col addrs */ +.equ            COL09_ADR,  0x0e000600    /*  9 col addrs */ +.equ            COL08_ADR,  0x0e000200    /*  8 col addrs */ +.equ            ROW14_ADR,  0x0f000000    /* 14 row addrs */ +.equ            ROW13_ADR,  0x07000000    /* 13 row addrs */ +.equ            ROW12_ADR,  0x03000000    /* 12 row addrs */ +.equ            ROW11_ADR,  0x01000000    /* 11 row addrs/also bank switch */ +.equ            ROW10_ADR,  0x00000000    /* 10 row addrs/also bank switch */ +.equ            COL11_DATA, 0x0b0b0b0b    /* 11 col addrs */ +.equ            COL10_DATA, 0x0a0a0a0a    /* 10 col data */ +.equ            COL09_DATA, 0x09090909    /*  9 col data */ +.equ            COL08_DATA, 0x08080808    /*  8 col data */ +.equ            ROW14_DATA, 0x3f3f3f3f    /* 14 row data (MASK) */ +.equ            ROW13_DATA, 0x1f1f1f1f    /* 13 row data (MASK) */ +.equ            ROW12_DATA, 0x0f0f0f0f    /* 12 row data (MASK) */ +.equ            ROW11_DATA, 0x07070707    /* 11 row data/also bank switch (MASK) */ +.equ            ROW10_DATA, 0xaaaaaaaa    /* 10 row data/also bank switch (MASK) */ + + + /* +  * initialize dram controller registers +  */ +.globl mem_init +mem_init:  +        xorw    %ax,%ax +        movl    $DBCTL, %edi              +fs	movb     %al, (%edi)             /* disable write buffer */ + +        movl    $ECCCTL, %edi             +fs	movb     %al, (%edi)             /* disable ECC */ + +        movl    $DRCTMCTL, %edi            +        movb    $0x1E,%al                /* Set SDRAM timing for slowest */ +fs	movb     %al, (%edi) + + /* +  * setup loop to do 4 external banks starting with bank 3 +  */ +        movl    $0xff000000,%eax         /* enable last bank and setup */ +        movl    $DRCBENDADR, %edi        /* ending address register */ +fs	movl     %eax, (%edi) + +        movl    $DRCCFG, %edi            /* setup */ +        movw    $0xbbbb,%ax              /* dram config register for  */ +fs	movw    %ax, (%edi) + + /* +  * issue a NOP to all DRAMs +  */ +        movl    $DRCCTL, %edi            /* setup DRAM control register with */ +        movb    $0x1,%al                 /* Disable refresh,disable write buffer */  +fs	movb     %al, (%edi) +        movl    $CACHELINESZ, %esi       /* just a dummy address to write for */  +fs	movw     %ax, (%esi) + /* +  * delay for 100 usec? 200? +  * ******this is a cludge for now ************* +  */ +        movw    $100,%cx +sizdelay:  +        loop    sizdelay                 /* we need 100 usec here */ + /***********************************************/ + + /* +  * issue all banks precharge +  */ +        movb    $0x2,%al                 /* All banks precharge */ +fs	movb     %al, (%edi) +fs	movw     %ax, (%esi) + + /* +  * issue 2 auto refreshes to all banks  +  */ +        movb    $0x4,%al                 /* Auto refresh cmd */ +fs	movb     %al, (%edi) +        movw    $2,%cx +refresh1:  +fs	movw     %ax, (%esi) +        loop    refresh1 + + /* +  * issue LOAD MODE REGISTER command +  */ +        movb    $0x3,%al                 /* Load mode register cmd */ +fs	movb     %al, (%edi) +fs	movw     %ax, (%esi) + + /* +  * issue 8 more auto refreshes to all banks  +  */  +        movb    $0x4,%al                 /* Auto refresh cmd */ +fs	movb     %al, (%edi) +        movw    $8,%cx +refresh2:  +fs	movw     %ax, (%esi) +        loop    refresh2 + + /* +  * set control register to NORMAL mode  +  */ +        movb    $0x0,%al                 /* Normal mode value */ +fs	movb     %al, (%edi) + + /* +  * size dram starting with external bank 3 moving to external bank 0 +  */ +        movl    $0x3,%ecx                /* start with external bank 3 */ + +nextbank:  + + /* +  * write col 11 wrap adr +  */ +        movl    $COL11_ADR, %esi         /* set address to max col (11) wrap addr */ +        movl    $COL11_DATA, %eax        /* pattern for max supported columns(11) */ +fs      movl    %eax, (%esi)             /* write max col pattern at max col adr */ +fs      movl    (%esi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write col 10 wrap adr +  */ + +        movl    $COL10_ADR, %esi         /* set address to 10 col wrap address */ +        movl    $COL10_DATA, %eax        /* pattern for 10 col wrap */ +fs      movl    %eax, (%esi)             /* write 10 col pattern @ 10 col wrap adr */ +fs      movl    (%esi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write col 9 wrap adr +  */ +        movl    $COL09_ADR, %esi         /* set address to 9 col wrap address */ +        movl    $COL09_DATA, %eax        /* pattern for 9 col wrap */ +fs      movl    %eax, (%esi)             /* write 9 col pattern @ 9 col wrap adr */ +fs      movl    (%esi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write col 8 wrap adr +  */ +        movl    $COL08_ADR, %esi         /* set address to min(8) col wrap address */ +        movl    $COL08_DATA, %eax        /* pattern for min (8) col wrap */ +fs      movl    %eax, (%esi)             /* write min col pattern @ min col adr */ +fs      movl    (%esi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write row 14 wrap adr +  */ +        movl    $ROW14_ADR, %esi         /* set address to max row (14) wrap addr */ +        movl    $ROW14_DATA, %eax        /* pattern for max supported rows(14) */ +fs      movl    %eax, (%esi)             /* write max row pattern at max row adr */ +fs      movl    (%esi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write row 13 wrap adr +  */ +        movl    $ROW13_ADR, %esi         /* set address to 13 row wrap address */ +        movl    $ROW13_DATA, %eax        /* pattern for 13 row wrap */ +fs      movl    %eax, (%esi)             /* write 13 row pattern @ 13 row wrap adr */ +fs      movl    (%esi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write row 12 wrap adr +  */ +        movl    $ROW12_ADR, %esi         /* set address to 12 row wrap address */ +        movl    $ROW12_DATA, %eax        /* pattern for 12 row wrap */ +fs      movl    %eax, (%esi)             /* write 12 row pattern @ 12 row wrap adr */ +fs      movl    (%esi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write row 11 wrap adr +  */ +        movl    $ROW11_ADR, %edi         /* set address to 11 row wrap address */ +        movl    $ROW11_DATA, %eax        /* pattern for 11 row wrap */ +fs      movl    %eax, (%edi)             /* write 11 row pattern @ 11 row wrap adr */ +fs      movl    (%edi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * write row 10 wrap adr --- this write is really to determine number of banks +  */ +        movl    $ROW10_ADR, %edi         /* set address to 10 row wrap address */ +        movl    $ROW10_DATA, %eax        /* pattern for 10 row wrap (AA) */ +fs      movl    %eax, (%edi)             /* write 10 row pattern @ 10 row wrap adr */ +fs      movl    (%edi), %ebx             /* optional read */ +        cmpl    %ebx,%eax                /* to verify write */ +        jnz     bad_ram                  /* this ram is bad */ + /* +  * read data @ row 12 wrap adr to determine  * banks,  +  * and read data @ row 14 wrap adr to determine  * rows. +  * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM. +  * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4  +  * if data @ row 12 wrap == 11 or 12, we have 4 banks, +  */ +        xorw    %di,%di                  /* value for 2 banks in DI */ +fs      movl    (%esi), %ebx             /* read from 12 row wrap to check banks  +                                          * (esi is setup from the write to row 12 wrap) */ +        cmpl    %ebx,%eax                /* check for AA pattern  (eax holds the aa pattern) */ +        jz      only2                    /* if pattern == AA, we only have 2 banks */ + +	/* 4 banks */ +	 +        movw    $8,%di                   /* value for 4 banks in DI (BNK_CNT bit) */ +        cmpl    $ROW11_DATA, %ebx        /* only other legitimate values are 11 */ +        jz      only2 +        cmpl    $ROW12_DATA, %ebx        /* and 12 */ +        jnz     bad_ram                  /* its bad if not 11 or 12! */ +	 +	/* fall through */ +only2:  + /* +  * validate row mask +  */ +        movl    $ROW14_ADR, %esi         /* set address back to max row wrap addr */ +fs      movl    (%esi), %eax             /* read actual number of rows @ row14 adr */ + +        cmpl    $ROW11_DATA, %eax        /* row must be greater than 11 pattern */ +        jb      bad_ram + +        cmpl    $ROW14_DATA, %eax        /* and row must be less than 14 pattern */ +        ja      bad_ram + +        cmpb    %ah,%al                  /* verify all 4 bytes of dword same */ +        jnz     bad_ram +        movl    %eax,%ebx +        shrl    $16,%ebx +        cmpw    %bx,%ax +        jnz     bad_ram + /* +  * read col 11 wrap adr for real column data value +  */ +        movl    $COL11_ADR, %esi         /* set address to max col (11) wrap addr */ +fs      movl    (%esi), %eax             /* read real col number at max col adr */ + /* +  * validate column data +  */ +        cmpl    $COL08_DATA, %eax        /* col must be greater than 8 pattern */ +        jb      bad_ram + +        cmpl    $COL11_DATA, %eax        /* and row must be less than 11 pattern */ +        ja      bad_ram + +        subl    $COL08_DATA, %eax        /* normalize column data to zero */ +        jc      bad_ram +        cmpb    %ah,%al                  /* verify all 4 bytes of dword equal */ +        jnz     bad_ram +        movl    %eax,%edx +        shrl    $16,%edx +        cmpw    %dx,%ax +        jnz     bad_ram + /* +  * merge bank and col data together +  */ +        addw    %di,%dx                  /* merge of bank and col info in dl */ + /* +  * fix ending addr mask based upon col info +  */ +        movb    $3,%al +        subb    %dh,%al                  /* dh contains the overflow from the bank/col merge  */ +        movb    %bl,%dh                  /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */ +        xchgw   %cx,%ax                  /* cx = ax = 3 or 2 depending on 2 or 4 bank device */ +        shrb    %cl,%dh	                 /*  */ +        incb    %dh                      /* ending addr is 1 greater than real end */ +        xchgw   %cx,%ax                  /* cx is bank number again */ + /* +  * issue all banks precharge +  */ +bad_reint:  +        movl    $DRCCTL, %esi            /* setup DRAM control register with */ +        movb    $0x2,%al                 /* All banks precharge */ +fs	movb     %al, (%esi) +        movl    $CACHELINESZ, %esi       /* address to init read buffer */ +fs	movw     %ax, (%esi) + + /* +  * update ENDING ADDRESS REGISTER +  */ +        movl    $DRCBENDADR, %edi        /* DRAM ending address register */ +        movl    %ecx,%ebx +	addl	%ebx, %edi +fs	movb    %dh, (%edi) + /* +  * update CONFIG REGISTER +  */ +        xorb    %dh,%dh +        movw    $0x00f,%bx +        movw    %cx,%ax +        shlw    $2,%ax +        xchgw   %cx,%ax +        shlw    %cl,%dx +        shlw    %cl,%bx +        notw    %bx +        xchgw   %cx,%ax +        movl    $DRCCFG, %edi +fs	mov     (%edi), %ax +        andw    %bx,%ax +        orw     %dx,%ax +fs      movw    %ax, (%edi) +        jcxz    cleanup + +        decw    %cx +        movl    %ecx,%ebx +        movl    $DRCBENDADR, %edi        /* DRAM ending address register */ +        movb    $0xff,%al +	addl	%ebx, %edi +fs	movb    %al, (%edi) + /* +  * set control register to NORMAL mode  +  */ +        movl    $DRCCTL, %esi            /* setup DRAM control register with */ +        movb    $0x0,%al                 /* Normal mode value */ +fs	movb    %al, (%esi) +        movl    $CACHELINESZ, %esi       /* address to init read buffer */ +fs	movw    %ax, (%esi) +        jmp     nextbank + +cleanup:  +        movl    $DRCBENDADR, %edi        /* DRAM ending address register  */ +        movw    $4,%cx +        xorw    %ax,%ax +cleanuplp:  +fs	movb   (%edi), %al +        orb     %al,%al +        jz      emptybank + +        addb    %ah,%al +        jns     nottoomuch + +        movb    $0x7f,%al +nottoomuch:  +        movb    %al,%ah +        orb     $0x80,%al +fs	movb    %al, (%edi) +emptybank:  +        incl    %edi +        loop    cleanuplp + +#if defined(CFG_SDRAM_CAS_LATENCY_2T) || defined(CFG_SDRAM_CAS_LATENCY_3T) +	/* set the CAS latency now since it is hard to do +	 * when we run from the RAM */ +	movl    $DRCTMCTL, %edi          /* DRAM timing register */ +	movb    (%edi), %al	 +#ifdef CFG_SDRAM_CAS_LATENCY_2T +	andb    $0xef, %al +#endif +#ifdef CFG_SDRAM_CAS_LATENCY_3T +	orb     $0x10, %al +#endif	  +	movb    %al, (%edi) +#endif +        movl    $DRCCTL, %edi            /* DRAM Control register */ +        movb    $0x3,%al                 /* Load mode register cmd */ +fs	movb     %al, (%edi) +fs	movw     %ax, (%esi) + + +        movl    $DRCCTL, %edi            /* DRAM Control register */ +        movb    $0x18,%al                /*  Enable refresh and NORMAL mode */ +fs	movb    %al, (%edi) + +        jmp     dram_done + +bad_ram:  +        xorl    %edx,%edx +        xorl    %edi,%edi +        jmp     bad_reint + +dram_done:  +	 +	/* readback DRCBENDADR and return the number +	 * of available ram bytes in %eax */  + +        movl    $DRCBENDADR, %edi        /* DRAM ending address register  */ +	 +	movl	(%edi), %eax +	movl	%eax, %ecx +	andl	$0x80000000, %ecx +	jz	bank2 +	andl	$0x7f000000, %eax +	shrl	$2, %eax  +	movl	%eax, %ebx + +bank2: 	movl	(%edi), %eax +	movl	%eax, %ecx +	andl	$0x00800000, %ecx +	jz	bank1 +	andl	$0x007f0000, %eax +	shll	$6, %eax  +	movl	%eax, %ebx + +bank1: 	movl	(%edi), %eax +	movl	%eax, %ecx +	andl	$0x00008000, %ecx +	jz	bank0 +	andl	$0x00007f00, %eax +	shll	$14, %eax  +	movl	%eax, %ebx + +bank0: 	movl	(%edi), %eax +	movl	%eax, %ecx +	andl	$0x00000080, %ecx +	jz	done +	andl	$0x0000007f, %eax +	shll	$22, %eax  +	movl	%eax, %ebx + +done:	movl	%ebx, %eax + +	jmp	*%ebp diff --git a/lib_i386/pci_type1.c b/lib_i386/pci_type1.c new file mode 100644 index 000000000..e5577e820 --- /dev/null +++ b/lib_i386/pci_type1.c @@ -0,0 +1,57 @@ +/* + * Support for type PCI configuration cycles. + * based on pci_indirect.c + * + * Copyright (C) 2002 Daniel Engström, Omicron Ceti AB, daniel@omicron.se. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <common.h> + +#ifdef CONFIG_PCI + +#include <asm/processor.h> +#include <asm/io.h> +#include <pci.h> + +#define cfg_read(val, addr, type, op)	*val = op((type)(addr)) +#define cfg_write(val, addr, type, op)	op((val), (type *)(addr)) + +#define TYPE1_PCI_OP(rw, size, type, op, mask)			 \ +static int								 \ +type1_##rw##_config_##size(struct pci_controller *hose, 		 \ +			      pci_dev_t dev, int offset, type val)	 \ +{									 \ +	outl(dev | (offset & 0xfc) | 0x80000000, hose->cfg_addr); 	 \ +	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);	 \ +	return 0;    					 		 \ +} + + +TYPE1_PCI_OP(read, byte, u8 *, inb, 3) +TYPE1_PCI_OP(read, word, u16 *, inw, 2) +TYPE1_PCI_OP(read, dword, u32 *, inl, 0) + +TYPE1_PCI_OP(write, byte, u8, outb, 3) +TYPE1_PCI_OP(write, word, u16, outw, 2) +TYPE1_PCI_OP(write, dword, u32, outl, 0) + +void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) +{ +	pci_set_ops(hose, +		    type1_read_config_byte, +		    type1_read_config_word, +		    type1_read_config_dword, +		    type1_write_config_byte, +		    type1_write_config_word, +		    type1_write_config_dword); + +	hose->cfg_addr = (unsigned int *) cfg_addr; +	hose->cfg_data = (unsigned char *) cfg_data; +} + +#endif diff --git a/lib_i386/realmode.c b/lib_i386/realmode.c new file mode 100644 index 000000000..372147cf2 --- /dev/null +++ b/lib_i386/realmode.c @@ -0,0 +1,69 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/ptrace.h> + + +#define REALMODE_BASE    ((char*)0x7c0) +#define REALMODE_MAILBOX ((char*)0xe00) + + +extern char realmode_enter; + + +int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out) +{ +	 +	/* setup out thin bios emulation */ +	if (bios_setup()) { +		return -1; +	} +		 +	/* copy the realmode switch code */ +	if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) { +		printf("realmode switch too large (%ld bytes, max is %d)\n",  +		       i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE)); +		return -1; +	} +	 +	memcpy(REALMODE_BASE, i386boot_realmode, i386boot_realmode_size); +		 +	 +	in->eip = off; +	in->xcs = seg; +	if (3>in->esp & 0xffff) { +		printf("Warning: entering realmode with sp < 4 will fail\n"); +	} +	 +	memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs)); +	 +	__asm__ volatile (  +		 "lcall $0x20,%0\n"  : :  "i" (&realmode_enter) ); + +	memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs)); + +	return out->eax; +} + diff --git a/lib_i386/realmode_switch.S b/lib_i386/realmode_switch.S new file mode 100644 index 000000000..9f212c2e8 --- /dev/null +++ b/lib_i386/realmode_switch.S @@ -0,0 +1,223 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +/* 32bit -> 16bit -> 32bit mode switch code */ + +/* + * Stack frame at 0xe00 + *      e00 ebx; + *	e04 ecx; + *	e08 edx; + *	e0c esi; + *	e10 edi; + *	e14 ebp;  + *	e18 eax; + *	e1c ds;   + *	e20 es; + *	e24 fs;   + *	e28 gs; + *	e2c orig_eax; + *	e30 eip; + *	e34 cs; + *	e38 eflags; + *	e3c esp; + *	e40 ss; + */ + +#define a32		.byte 0x67;		/* address size prefix 32 */ +#define o32		.byte 0x66;		/* operand size prefix 32 */  + +.section .realmode, "ax" +.code16 + +						/* 16bit protected mode code here */ +.globl realmode_enter +realmode_enter: +o32	pusha +o32	pushf +	cli +        sidt   	saved_idt +        sgdt    saved_gdt +        movl    %esp, %eax +        movl    %eax, saved_protected_mode_esp +	 +	movl	$0x10, %eax +	movl    %eax, %esp +	movw	$0x28, %ax +	movw	%ax, %ds +	movw	%ax, %es +	movw	%ax, %fs +	movw	%ax, %gs + +	lidt	realmode_idt_ptr +	movl	%cr0, %eax                	/* Go back into real mode by */ +	andl	$0x7ffffffe, %eax         	/* clearing PE to 0 */ +	movl	%eax, %cr0 +	ljmp	$0x0,$do_realmode             	/* switch to real mode */ +						 +do_realmode:					/* realmode code from here */  +	movw	%cs,%ax +	movw	%ax,%ds +	movw	%ax,%es +	movw	%ax,%fs +	movw	%ax,%gs +	 +						/* create a temporary stack */ +	                                +	movw	$0xc0, %ax              +	movw	%ax, %ss                 +	movw	$0x200, %ax            +	movw	%ax, %sp  +	 +	popl	%ebx +	popl	%ecx +	popl	%edx +	popl	%esi +	popl	%edi +	popl	%ebp +	popl	%eax +	movl	%eax, temp_eax +	popl	%eax +	movw	%ax, %ds +	popl	%eax +	movw	%ax, %es +	popl	%eax +	movw	%ax, %fs +	popl	%eax +	movw	%ax, %gs +	popl	%eax				/* orig_eax */ +	popl	%eax +cs	movw	%ax, temp_ip +	popl	%eax +cs	movw	%ax, temp_cs +o32	popf +	popl	%eax +	popw	%ss +	movl	%eax, %esp +cs	movl	temp_eax, %eax +	wbinvd                                  /* self-modifying code, +						 * better flush the cache */ +	 +	.byte	0x9a				/* lcall */ +temp_ip: +	.word	0	     			/* new ip */ +temp_cs:	 +	.word   0				/* new cs */ +realmode_ret: +						/* save eax, esp and ss */ +cs	movl	%eax, saved_eax +	movl	%esp, %eax +cs	movl	%eax, saved_esp +	movw    %ss, %ax +cs	movw	%ax, saved_ss +	 +	/* restore the stack, note that we set sp to 0x244; +	 * pt_regs is 0x44 bytes long and we push the structure +	 * backwards on to the stack, bottom first */ +	  +	movw	$0xc0, %ax              +	movw	%ax, %ss                 +	movw	$0x244, %ax            +	movw	%ax, %sp  +	 +	xorl	%eax,%eax +cs	movw	saved_ss, %ax +	pushl	%eax +cs	movl	saved_esp, %eax +	pushl	%eax +o32	pushf +	xorl	%eax,%eax +cs	movw	temp_cs, %ax +	pushl	%eax +cs	movw	temp_ip, %ax +	pushl	%eax +	pushl	$0 +	movw	%gs, %ax +	pushl	%eax +	movw	%fs, %ax +	pushl	%eax +	movw	%es, %ax +	pushl	%eax +	movw	%ds, %ax +	pushl	%eax +	movl	saved_eax, %eax +	pushl	%eax +	pushl	%ebp +	pushl	%edi +	pushl	%esi +	pushl	%edx +	pushl	%ecx +	pushl	%ebx + +o32 cs	lidt	saved_idt +o32 cs	lgdt    saved_gdt			/* Set GDTR */ + +        movl    %cr0, %eax              	/* Go back into protected mode */ +        orl     $1,%eax                 	/* reset PE to 1 */ +        movl    %eax, %cr0                +        jmp     next_line               	/* flush prefetch queue */ +next_line:     +        movw	$return_ptr, %ax           +        movw    %ax,%bp +o32 cs	ljmp	*(%bp) + +.code32 +protected_mode: +        movl    $0x18,%eax         		/* reload GDT[3] */ +        movw    %ax,%fs                 	/* reset FS */ +	movw	%ax,%ds                		/* reset DS */ +        movw    %ax,%gs                 	/* reset GS */ +        movw    %ax,%es                 	/* reset ES */ +        movw    %ax,%ss                 	/* reset SS */ +        movl    saved_protected_mode_esp, %eax +	movl	%eax, %esp +	popf +	popa +        ret + +temp_eax: +	.long	0 + +saved_ss: +	.word   0 +saved_esp: +	.long	0 +saved_eax: +	.long	0 +	 +realmode_idt_ptr: +	.word	0x400			        +	.word	0x0, 0x0		 +	 +saved_gdt:   +  	.word 	0, 0, 0, 0 +saved_idt: +  	.word 	0, 0, 0, 0 + +saved_protected_mode_esp: +	.long 	0 +	 +return_ptr: +	.long	protected_mode +	.word	0x10 diff --git a/lib_i386/zimage.c b/lib_i386/zimage.c new file mode 100644 index 000000000..190d46ef7 --- /dev/null +++ b/lib_i386/zimage.c @@ -0,0 +1,276 @@ +/* + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, daniel@omicron.se + *  + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/*  + * Linux i386 zImage and bzImage loading + *  + * based on the procdure described in  + * linux/Documentation/i386/boot.txt + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/ptrace.h> +#include <asm/zimage.h> +#include <asm/realmode.h> +#include <asm/byteorder.h> + +/* + * Memory lay-out: + *  + * relative to setup_base (which is 0x90000 currently) + *  + *	0x0000-0x7FFF	Real mode kernel    + *	0x8000-0x8FFF	Stack and heap + *	0x9000-0x90FF	Kernel command line + */ +#define DEFAULT_SETUP_BASE  0x90000 +#define COMMAND_LINE_OFFSET 0x9000 +#define HEAP_END_OFFSET     0x8e00 + +#define COMMAND_LINE_SIZE   2048 + +static void build_command_line(char *command_line, int auto_boot) +{ +	char *env_command_line; +	 +	command_line[0] = '\0'; +	 +	env_command_line =  getenv("bootargs"); +	 +	/* set console= argument if we use a serial console */ +	if (NULL == strstr(env_command_line, "console=")) { +		if (0==strcmp(getenv("stdout"), "serial")) { +			 +			/* We seem to use serial console */ +			sprintf(command_line, "console=ttyS0,%s ",  +				 getenv("baudrate")); +		} +	} +	 +	if (auto_boot) { +		strcat(command_line, "auto "); +	} +		 +	if (NULL != env_command_line) { +		strcat(command_line, env_command_line); +	}  +	 +	 +	printf("Kernel command line: \"%s\"\n", command_line); +} + +void *load_zimage(char *image, unsigned long kernel_size,  +		  unsigned long initrd_addr, unsigned long initrd_size, +		  int auto_boot) +{ +        void *setup_base; +	int setup_size; +	int bootproto; +	int big_image; +	void *load_address; +	 +	 +	setup_base = (void*)DEFAULT_SETUP_BASE;	/* base address for real-mode segment */ +	 + 	if (KERNEL_MAGIC != *(u16*)(image + BOOT_FLAG_OFF)) { +		printf("Error: Invalid kernel magic (found 0x%04x, expected 0xaa55)\n", +		       *(u16*)(image + BOOT_FLAG_OFF)); +		return 0; +	} +	 +	 +	/* determine boot protocol version */ +	if (KERNEL_V2_MAGIC == *(u32*)(image+HEADER_OFF)) { +		bootproto = *(u16*)(image+VERSION_OFF); +	} else { +		/* Very old kernel */ +		bootproto = 0x0100; +	} +	 +	/* determine size of setup */ +	if (0 == *(u8*)(image + SETUP_SECTS_OFF)) { +		setup_size = 5 * 512; +	} else { +		setup_size = (*(u8*)(image + SETUP_SECTS_OFF) + 1) * 512; +	} +	 +	if (setup_size > SETUP_MAX_SIZE) { +		printf("Error: Setup is too large (%d bytes)\n", setup_size); +	} +	 +	/* Determine image type */ +  	big_image = (bootproto >= 0x0200) && (*(u8*)(image + LOADFLAGS_OFF) & BIG_KERNEL_FLAG); +	 +	/* Derermine load address */ +	load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR:ZIMAGE_LOAD_ADDR); +			 +	/* load setup */ +	memmove(setup_base, image, setup_size); +	 +	printf("Using boot protocol version %x.%02x\n",  +	       (bootproto & 0xff00) >> 8, bootproto & 0xff); +	 +	 +	if (bootproto == 0x0100) {		 +	 +		*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; +		*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;  +		 +		/* A very old kernel MUST have its real-mode code +		 * loaded at 0x90000 */ +		 +		if ((u32)setup_base != 0x90000) { +			/* Copy the real-mode kernel */ +			memmove((void*)0x90000, setup_base, setup_size); +			/* Copy the command line */ +			memmove((void*)0x99000, setup_base+COMMAND_LINE_OFFSET,  +			       COMMAND_LINE_SIZE); +			 +			setup_base = (void*)0x90000;		 /* Relocated */ +		} +		 +		/* It is recommended to clear memory up to the 32K mark */ +		memset((void*)0x90000 + setup_size, 0, SETUP_MAX_SIZE-setup_size); +	} +	 +	if (bootproto >= 0x0200) { +		*(u8*)(setup_base + TYPE_OF_LOADER_OFF) = 0xff; +		printf("Linux kernel version %s\n",  +		       (char*)(setup_base + SETUP_START_OFFSET +  +			       *(u16*)(setup_base + START_SYS_OFF + 2))); +		 +		if (initrd_addr) { +			printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n", +			       initrd_addr, initrd_size); +			 +			*(u32*)(setup_base + RAMDISK_IMAGE_OFF) = initrd_addr; +			*(u32*)(setup_base + RAMDISK_SIZE_OFF)=initrd_size; +		} +	} +	 +	if (bootproto >= 0x0201) { +		*(u16*)(setup_base + HEAP_END_PTR_OFF) = HEAP_END_OFFSET; +		 +		/* CAN_USE_HEAP */ +		*(u8*)(setup_base + LOADFLAGS_OFF) =  +			*(u8*)(setup_base + LOADFLAGS_OFF) | HEAP_FLAG; +	} +	 +	if (bootproto >= 0x0202) { +		*(u32*)(setup_base + CMD_LINE_PTR_OFF) = (u32)setup_base + COMMAND_LINE_OFFSET; +	} else if (bootproto >= 0x0200) { +		*(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; +		*(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;  +		*(u16*)(setup_base + SETUP_MOVE_SIZE_OFF) = 0x9100; +	} +	 + +	 +	if (big_image) { +		if ((kernel_size - setup_size) > BZIMAGE_MAX_SIZE) {  +			printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n", +			       kernel_size - setup_size, BZIMAGE_MAX_SIZE); +			return 0; +		} +		 +	} else if ((kernel_size - setup_size) > ZIMAGE_MAX_SIZE) { +		printf("Error: zImage kernel too big! (size: %ld, max: %d)\n", +		       kernel_size - setup_size, ZIMAGE_MAX_SIZE); +		return 0; +	} +	 +	/* build command line at COMMAND_LINE_OFFSET */ +	build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot); +	 +        printf("Loading %czImage at address 0x%08x (%ld bytes)\n", big_image ? 'b' : ' ',  +	       (u32)load_address, kernel_size - setup_size); + +	        +	memmove(load_address, image + setup_size, kernel_size - setup_size); +	 +	/* ready for booting */ +	return setup_base; +} + + +void boot_zimage(void *setup_base) +{ +	struct pt_regs regs; +	 +	memset(®s, 0, sizeof(struct pt_regs)); +	regs.xds = (u32)setup_base >> 4; +	regs.xss = 0x8e00; +	regs.esp = 0x200; +	regs.eflags = 0; +	enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, ®s); +} + + +image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size) +{	 +	/* There is no way to know the size of a zImage ... * +	 * so we assume that 2MB will be enough for now */ +#define ZIMAGE_SIZE 0x200000 +	 +	/* load a 1MB, the loaded will have to be moved to its final +	 * position again later... */ +#define ZIMAGE_LOAD 0x100000 +	 +	ulong checksum; +	 + 	if (KERNEL_MAGIC != *(u16*)(ptr + BOOT_FLAG_OFF)) { +		/* not a zImage or bzImage */ +		return NULL; +	} + +	if (-1 == size) { +		size = ZIMAGE_SIZE; +	} +#if 0	 +	checksum = crc32 (0, ptr, size); +#else +	checksum = 0; +#endif		 +	memset(hdr, 0, sizeof(image_header_t)); +	 +	/* Build new header */ +	hdr->ih_magic = htonl(IH_MAGIC); +	hdr->ih_time  = 0; +	hdr->ih_size  = htonl(size); +	hdr->ih_load  = htonl(ZIMAGE_LOAD); +	hdr->ih_ep    = 0; +	hdr->ih_dcrc  = htonl(checksum); +	hdr->ih_os    = IH_OS_LINUX; +	hdr->ih_arch  = IH_CPU_I386; +	hdr->ih_type  = IH_TYPE_KERNEL; +	hdr->ih_comp  = IH_COMP_NONE; + +	strncpy((char *)hdr->ih_name, "(none)", IH_NMLEN); + +	checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); + +	hdr->ih_hcrc = htonl(checksum); +	 +	return hdr; +} |