* Patch by Daniel Engstrm, 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
This commit is contained in:
wdenk 2002-11-18 00:14:45 +00:00
parent 1d0350ed0b
commit 2262cfeef9
82 changed files with 10257 additions and 84 deletions

View File

@ -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)

View File

@ -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

View File

@ -249,6 +249,17 @@ Alex Z
lart SA1100
dnp1110 SA1110
#########################################################################
# x86 Systems: #
# #
# Maintainer Name, Email Address #
# Board CPU #
#########################################################################
Daniel Engström <daniel@omicron.se>
sc520_cdp x86
#########################################################################
# End of MAINTAINERS list #
#########################################################################

View File

@ -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:

6
README
View File

@ -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

47
board/sc520_cdp/Makefile Normal file
View File

@ -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
#########################################################################

25
board/sc520_cdp/config.mk Normal file
View File

@ -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

449
board/sc520_cdp/flash.c Normal file
View File

@ -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);
}

288
board/sc520_cdp/sc520_cdp.c Normal file
View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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) );
}

View File

@ -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 \

View File

@ -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[],

View File

@ -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;
}

145
common/cmd_fdos.c Normal file
View File

@ -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

View File

@ -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;

View File

@ -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

43
cpu/i386/Makefile Normal file
View File

@ -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
#########################################################################

26
cpu/i386/config.mk Normal file
View File

@ -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

62
cpu/i386/cpu.c Normal file
View File

@ -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;
}

583
cpu/i386/interrupts.c Normal file
View File

@ -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

38
cpu/i386/reset.S Normal file
View File

@ -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

460
cpu/i386/serial.c Normal file
View File

@ -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 */

198
cpu/i386/start.S Normal file
View File

@ -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

112
cpu/i386/start16.S Normal file
View File

@ -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) */

211
cpu/i386/timer.c Normal file
View File

@ -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

74
doc/README-i386 Normal file
View File

@ -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 }
};

39
doc/TODO-i386 Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -22,7 +22,7 @@
#
#
SUBDIRS := jffs2
SUBDIRS := jffs2 fdos
.depend all:
@for dir in $(SUBDIRS) ; do \

49
fs/fdos/Makefile Normal file
View File

@ -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
#########################################################################

195
fs/fdos/dev.c Normal file
View File

@ -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

177
fs/fdos/dos.h Normal file
View File

@ -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

145
fs/fdos/fat.c Normal file
View File

@ -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

175
fs/fdos/fdos.c Normal file
View File

@ -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

117
fs/fdos/fdos.h Normal file
View File

@ -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

120
fs/fdos/fs.c Normal file
View File

@ -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

348
fs/fdos/subdir.c Normal file
View File

@ -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

357
fs/fdos/vfat.c Normal file
View File

@ -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

24
i386_config.mk Normal file
View File

@ -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__

384
include/asm-i386/bitops.h Normal file
View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

56
include/asm-i386/i8254.h Normal file
View File

@ -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

88
include/asm-i386/i8259.h Normal file
View File

@ -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

47
include/asm-i386/ibmpc.h Normal file
View File

@ -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

View File

@ -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

249
include/asm-i386/ic/sc520.h Normal file
View File

@ -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

207
include/asm-i386/io.h Normal file
View File

@ -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

31
include/asm-i386/pci.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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_ */

66
include/asm-i386/ptrace.h Normal file
View File

@ -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

View File

@ -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

30
include/asm-i386/string.h Normal file
View File

@ -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

51
include/asm-i386/types.h Normal file
View File

@ -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

58
include/asm-i386/u-boot.h Normal file
View File

@ -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_ */

75
include/asm-i386/zimage.h Normal file
View File

@ -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

View File

@ -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
*/

55
include/cmd_fdos.h Normal file
View File

@ -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 */

View File

@ -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);

View File

@ -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 \

View File

@ -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 | \

View File

@ -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 & \

View File

@ -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 | \

210
include/configs/sc520_cdp.h Normal file
View File

@ -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 */

41
include/fdc.h Normal file
View File

@ -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

View File

@ -67,7 +67,7 @@ struct stat {
#endif /* __PPC__ */
#ifdef __ARM__
#if defined (__ARM__) || defined (__I386__)
struct stat {
unsigned short st_dev;

45
lib_i386/Makefile Normal file
View File

@ -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
#########################################################################

443
lib_i386/bios.S Normal file
View File

@ -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

178
lib_i386/bios_setup.c Normal file
View File

@ -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;
}

448
lib_i386/board.c Normal file
View File

@ -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 (;;);
}

174
lib_i386/i386_linux.c Normal file
View File

@ -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);
}

442
lib_i386/ic/ali512x.c Normal file
View File

@ -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;
}

348
lib_i386/ic/sc520.c Normal file
View File

@ -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

530
lib_i386/ic/sc520_asm.S Normal file
View File

@ -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

57
lib_i386/pci_type1.c Normal file
View File

@ -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

69
lib_i386/realmode.c Normal file
View File

@ -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;
}

223
lib_i386/realmode_switch.S Normal file
View File

@ -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

276
lib_i386/zimage.c Normal file
View File

@ -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(&regs, 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, &regs, &regs);
}
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;
}