* 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:
parent
1d0350ed0b
commit
2262cfeef9
@ -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)
|
||||
|
4
CREDITS
4
CREDITS
@ -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
|
||||
|
11
MAINTAINERS
11
MAINTAINERS
@ -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 #
|
||||
#########################################################################
|
||||
|
19
Makefile
19
Makefile
@ -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
6
README
@ -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
47
board/sc520_cdp/Makefile
Normal 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
25
board/sc520_cdp/config.mk
Normal 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
449
board/sc520_cdp/flash.c
Normal 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
288
board/sc520_cdp/sc520_cdp.c
Normal 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);
|
||||
}
|
86
board/sc520_cdp/sc520_cdp_asm.S
Normal file
86
board/sc520_cdp/sc520_cdp_asm.S
Normal 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
|
||||
|
62
board/sc520_cdp/sc520_cdp_asm16.S
Normal file
62
board/sc520_cdp/sc520_cdp_asm16.S
Normal 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
|
||||
|
85
board/sc520_cdp/u-boot.lds
Normal file
85
board/sc520_cdp/u-boot.lds
Normal 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) );
|
||||
}
|
@ -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 \
|
||||
|
@ -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[],
|
||||
|
@ -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
145
common/cmd_fdos.c
Normal 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
|
174
common/cmd_ide.c
174
common/cmd_ide.c
@ -44,6 +44,9 @@
|
||||
#ifdef CONFIG_STATUS_LED
|
||||
# include <status_led.h>
|
||||
#endif
|
||||
#ifdef __I386__
|
||||
#include <asm/io.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
# include <status_led.h>
|
||||
@ -114,7 +117,9 @@ ulong ide_bus_offset[CFG_IDE_MAXBUS] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __PPC__
|
||||
#define ATA_CURR_BASE(dev) (CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)])
|
||||
#endif
|
||||
|
||||
static int ide_bus_ok[CFG_IDE_MAXBUS];
|
||||
|
||||
@ -142,9 +147,11 @@ static uchar ide_wait (int dev, ulong t);
|
||||
|
||||
#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
|
||||
|
||||
static void __inline__ outb(int dev, int port, unsigned char val);
|
||||
static unsigned char __inline__ inb(int dev, int port);
|
||||
static void __inline__ ide_outb(int dev, int port, unsigned char val);
|
||||
static unsigned char __inline__ ide_inb(int dev, int port);
|
||||
#ifdef __PPC__
|
||||
static void input_swap_data(int dev, ulong *sect_buf, int words);
|
||||
#endif
|
||||
static void input_data(int dev, ulong *sect_buf, int words);
|
||||
static void output_data(int dev, ulong *sect_buf, int words);
|
||||
static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
|
||||
@ -517,14 +524,14 @@ void ide_init (void)
|
||||
/* Select device
|
||||
*/
|
||||
udelay (100000); /* 100 ms */
|
||||
outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
|
||||
ide_outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev));
|
||||
udelay (100000); /* 100 ms */
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
udelay (10000); /* 10 ms */
|
||||
|
||||
c = inb (dev, ATA_STATUS);
|
||||
c = ide_inb (dev, ATA_STATUS);
|
||||
i++;
|
||||
if (i > (ATA_RESET_TIME * 100)) {
|
||||
puts ("** Timeout **\n");
|
||||
@ -679,30 +686,48 @@ set_pcmcia_timing (int pmode)
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __PPC__
|
||||
static void __inline__
|
||||
outb(int dev, int port, unsigned char val)
|
||||
ide_outb(int dev, int port, unsigned char val)
|
||||
{
|
||||
/* Ensure I/O operations complete */
|
||||
__asm__ volatile("eieio");
|
||||
*((uchar *)(ATA_CURR_BASE(dev)+port)) = val;
|
||||
#if 0
|
||||
printf ("OUTB: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
|
||||
printf ("ide_outb: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
|
||||
#endif
|
||||
}
|
||||
#else /* ! __PPC__ */
|
||||
static void __inline__
|
||||
ide_outb(int dev, int port, unsigned char val)
|
||||
{
|
||||
outb(val, port);
|
||||
}
|
||||
#endif /* __PPC__ */
|
||||
|
||||
|
||||
#ifdef __PPC__
|
||||
static unsigned char __inline__
|
||||
inb(int dev, int port)
|
||||
ide_inb(int dev, int port)
|
||||
{
|
||||
uchar val;
|
||||
/* Ensure I/O operations complete */
|
||||
__asm__ volatile("eieio");
|
||||
val = *((uchar *)(ATA_CURR_BASE(dev)+port));
|
||||
#if 0
|
||||
printf ("INB: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
|
||||
printf ("ide_inb: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val);
|
||||
#endif
|
||||
return (val);
|
||||
}
|
||||
#else /* ! __PPC__ */
|
||||
static unsigned char __inline__
|
||||
ide_inb(int dev, int port)
|
||||
{
|
||||
return inb(port);
|
||||
}
|
||||
#endif /* __PPC__ */
|
||||
|
||||
#ifdef __PPC__
|
||||
__inline__ unsigned ld_le16(const volatile unsigned short *addr)
|
||||
{
|
||||
unsigned val;
|
||||
@ -722,7 +747,14 @@ input_swap_data(int dev, ulong *sect_buf, int words)
|
||||
*dbuf++ = ld_le16(pbuf);
|
||||
}
|
||||
}
|
||||
#else /* ! __PPC__ */
|
||||
#define input_swap_data(x,y,z) input_data(x,y,z)
|
||||
#endif /* __PPC__ */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __PPC__
|
||||
static void
|
||||
output_data(int dev, ulong *sect_buf, int words)
|
||||
{
|
||||
@ -738,7 +770,15 @@ output_data(int dev, ulong *sect_buf, int words)
|
||||
*pbuf = *dbuf++;
|
||||
}
|
||||
}
|
||||
#else /* ! __PPC__ */
|
||||
static void
|
||||
output_data(int dev, ulong *sect_buf, int words)
|
||||
{
|
||||
outsw(ATA_DATA_REG, sect_buf, words<<1);
|
||||
}
|
||||
#endif /* __PPC__ */
|
||||
|
||||
#ifdef __PPC__
|
||||
static void
|
||||
input_data(int dev, ulong *sect_buf, int words)
|
||||
{
|
||||
@ -754,6 +794,14 @@ input_data(int dev, ulong *sect_buf, int words)
|
||||
*dbuf++ = *pbuf;
|
||||
}
|
||||
}
|
||||
#else /* ! __PPC__ */
|
||||
static void
|
||||
input_data(int dev, ulong *sect_buf, int words)
|
||||
{
|
||||
insw(ATA_DATA_REG, sect_buf, words << 1);
|
||||
}
|
||||
|
||||
#endif /* __PPC__ */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
*/
|
||||
@ -773,19 +821,19 @@ static void ide_ident (block_dev_desc_t *dev_desc)
|
||||
ide_led (DEVICE_LED(device), 1); /* LED on */
|
||||
/* Select device
|
||||
*/
|
||||
outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
dev_desc->if_type=IF_TYPE_IDE;
|
||||
#ifdef CONFIG_ATAPI
|
||||
/* check signature */
|
||||
if ((inb(device,ATA_SECT_CNT)==0x01) &&
|
||||
(inb(device,ATA_SECT_NUM)==0x01) &&
|
||||
(inb(device,ATA_CYL_LOW)==0x14) &&
|
||||
(inb(device,ATA_CYL_HIGH)==0xEB)) {
|
||||
if ((ide_inb(device,ATA_SECT_CNT) == 0x01) &&
|
||||
(ide_inb(device,ATA_SECT_NUM) == 0x01) &&
|
||||
(ide_inb(device,ATA_CYL_LOW) == 0x14) &&
|
||||
(ide_inb(device,ATA_CYL_HIGH) == 0xEB)) {
|
||||
/* ATAPI Signature found */
|
||||
dev_desc->if_type=IF_TYPE_ATAPI;
|
||||
/* Start Ident Command
|
||||
*/
|
||||
outb (device, ATA_COMMAND, ATAPI_CMD_IDENT);
|
||||
ide_outb (device, ATA_COMMAND, ATAPI_CMD_IDENT);
|
||||
/*
|
||||
* Wait for completion - ATAPI devices need more time
|
||||
* to become ready
|
||||
@ -797,7 +845,7 @@ static void ide_ident (block_dev_desc_t *dev_desc)
|
||||
{
|
||||
/* Start Ident Command
|
||||
*/
|
||||
outb (device, ATA_COMMAND, ATA_CMD_IDENT);
|
||||
ide_outb (device, ATA_COMMAND, ATA_CMD_IDENT);
|
||||
|
||||
/* Wait for completion
|
||||
*/
|
||||
@ -867,15 +915,15 @@ static void ide_ident (block_dev_desc_t *dev_desc)
|
||||
#if 0 /* only used to test the powersaving mode,
|
||||
* if enabled, the drive goes after 5 sec
|
||||
* in standby mode */
|
||||
outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
c = ide_wait (device, IDE_TIME_OUT);
|
||||
outb (device, ATA_SECT_CNT, 1);
|
||||
outb (device, ATA_LBA_LOW, 0);
|
||||
outb (device, ATA_LBA_MID, 0);
|
||||
outb (device, ATA_LBA_HIGH, 0);
|
||||
outb (device, ATA_DEV_HD, ATA_LBA |
|
||||
ide_outb (device, ATA_SECT_CNT, 1);
|
||||
ide_outb (device, ATA_LBA_LOW, 0);
|
||||
ide_outb (device, ATA_LBA_MID, 0);
|
||||
ide_outb (device, ATA_LBA_HIGH, 0);
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA |
|
||||
ATA_DEVICE(device));
|
||||
outb (device, ATA_COMMAND, 0xe3);
|
||||
ide_outb (device, ATA_COMMAND, 0xe3);
|
||||
udelay (50);
|
||||
c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */
|
||||
#endif
|
||||
@ -897,7 +945,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
|
||||
/* Select device
|
||||
*/
|
||||
outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
c = ide_wait (device, IDE_TIME_OUT);
|
||||
|
||||
if (c & ATA_STAT_BUSY) {
|
||||
@ -907,7 +955,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
|
||||
/* first check if the drive is in Powersaving mode, if yes,
|
||||
* increase the timeout value */
|
||||
outb (device, ATA_COMMAND, ATA_CMD_CHK_PWR);
|
||||
ide_outb (device, ATA_COMMAND, ATA_CMD_CHK_PWR);
|
||||
udelay (50);
|
||||
|
||||
c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */
|
||||
@ -919,7 +967,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
|
||||
printf ("No Powersaving mode %X\n", c);
|
||||
} else {
|
||||
c = inb(device,ATA_SECT_CNT);
|
||||
c = ide_inb(device,ATA_SECT_CNT);
|
||||
PRINTF("Powersaving %02X\n",c);
|
||||
if(c==0)
|
||||
pwrsave=1;
|
||||
@ -935,14 +983,14 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
break;
|
||||
}
|
||||
|
||||
outb (device, ATA_SECT_CNT, 1);
|
||||
outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
|
||||
outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
|
||||
outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
|
||||
outb (device, ATA_DEV_HD, ATA_LBA |
|
||||
ide_outb (device, ATA_SECT_CNT, 1);
|
||||
ide_outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
|
||||
ide_outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
|
||||
ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA |
|
||||
ATA_DEVICE(device) |
|
||||
((blknr >> 24) & 0xF) );
|
||||
outb (device, ATA_COMMAND, ATA_CMD_READ);
|
||||
ide_outb (device, ATA_COMMAND, ATA_CMD_READ);
|
||||
|
||||
udelay (50);
|
||||
|
||||
@ -960,7 +1008,7 @@ ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
}
|
||||
|
||||
input_data (device, buffer, ATA_SECTORWORDS);
|
||||
(void) inb (device, ATA_STATUS); /* clear IRQ */
|
||||
(void) ide_inb (device, ATA_STATUS); /* clear IRQ */
|
||||
|
||||
++n;
|
||||
++blknr;
|
||||
@ -983,7 +1031,7 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
|
||||
/* Select device
|
||||
*/
|
||||
outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
|
||||
while (blkcnt-- > 0) {
|
||||
|
||||
@ -994,14 +1042,14 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
goto WR_OUT;
|
||||
}
|
||||
|
||||
outb (device, ATA_SECT_CNT, 1);
|
||||
outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
|
||||
outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
|
||||
outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
|
||||
outb (device, ATA_DEV_HD, ATA_LBA |
|
||||
ide_outb (device, ATA_SECT_CNT, 1);
|
||||
ide_outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF);
|
||||
ide_outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF);
|
||||
ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA |
|
||||
ATA_DEVICE(device) |
|
||||
((blknr >> 24) & 0xF) );
|
||||
outb (device, ATA_COMMAND, ATA_CMD_WRITE);
|
||||
ide_outb (device, ATA_COMMAND, ATA_CMD_WRITE);
|
||||
|
||||
udelay (50);
|
||||
|
||||
@ -1014,7 +1062,7 @@ ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
}
|
||||
|
||||
output_data (device, buffer, ATA_SECTORWORDS);
|
||||
c = inb (device, ATA_STATUS); /* clear IRQ */
|
||||
c = ide_inb (device, ATA_STATUS); /* clear IRQ */
|
||||
++n;
|
||||
++blknr;
|
||||
buffer += ATA_SECTORWORDS;
|
||||
@ -1063,7 +1111,7 @@ static uchar ide_wait (int dev, ulong t)
|
||||
ulong delay = 10 * t; /* poll every 100 us */
|
||||
uchar c;
|
||||
|
||||
while ((c = inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
|
||||
while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
|
||||
udelay (100);
|
||||
if (delay-- == 0) {
|
||||
break;
|
||||
@ -1188,6 +1236,7 @@ static void ide_led (uchar led, uchar status)
|
||||
#define AT_PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
#ifdef __PPC__
|
||||
/* since ATAPI may use commands with not 4 bytes alligned length
|
||||
* we have our own transfer functions, 2 bytes alligned */
|
||||
static void
|
||||
@ -1218,6 +1267,22 @@ input_data_shorts(int dev, ushort *sect_buf, int shorts)
|
||||
}
|
||||
}
|
||||
|
||||
#else /* ! __PPC__ */
|
||||
static void
|
||||
output_data_shorts(int dev, ushort *sect_buf, int shorts)
|
||||
{
|
||||
outsw(ATA_DATA_REG, sect_buf, shorts);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
input_data_shorts(int dev, ushort *sect_buf, int shorts)
|
||||
{
|
||||
insw(ATA_DATA_REG, sect_buf, shorts);
|
||||
}
|
||||
|
||||
#endif /* __PPC__ */
|
||||
|
||||
/*
|
||||
* Wait until (Status & mask) == res, or timeout (in ms)
|
||||
* Return last status
|
||||
@ -1229,9 +1294,8 @@ static uchar atapi_wait_mask (int dev, ulong t,uchar mask, uchar res)
|
||||
ulong delay = 10 * t; /* poll every 100 us */
|
||||
uchar c;
|
||||
|
||||
c = inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */
|
||||
while (((c = inb(dev, ATA_STATUS)) & mask)
|
||||
!= res) {
|
||||
c = ide_inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */
|
||||
while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) {
|
||||
/* break if error occurs (doesn't make sense to wait more) */
|
||||
if((c & ATA_STAT_ERR)==ATA_STAT_ERR)
|
||||
break;
|
||||
@ -1256,7 +1320,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
|
||||
*/
|
||||
mask = ATA_STAT_BUSY|ATA_STAT_DRQ;
|
||||
res = 0;
|
||||
outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
|
||||
if ((c & mask) != res) {
|
||||
printf ("ATAPI_ISSUE: device %d not ready status %X\n", device,c);
|
||||
@ -1264,12 +1328,12 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
|
||||
goto AI_OUT;
|
||||
}
|
||||
/* write taskfile */
|
||||
outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
|
||||
outb (device, ATA_CYL_LOW, (unsigned char)(buflen & 0xFF));
|
||||
outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF));
|
||||
outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
ide_outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */
|
||||
ide_outb (device, ATA_CYL_LOW, (unsigned char)(buflen & 0xFF));
|
||||
ide_outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF));
|
||||
ide_outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
|
||||
|
||||
outb (device, ATA_COMMAND, ATAPI_CMD_PACKET);
|
||||
ide_outb (device, ATA_COMMAND, ATAPI_CMD_PACKET);
|
||||
udelay (50);
|
||||
|
||||
mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR;
|
||||
@ -1295,7 +1359,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
|
||||
c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
|
||||
if ((c & mask) != res ) {
|
||||
if (c & ATA_STAT_ERR) {
|
||||
err=(inb(device,ATA_ERROR_REG))>>4;
|
||||
err=(ide_inb(device,ATA_ERROR_REG))>>4;
|
||||
AT_PRINTF("atapi_issue 1 returned sense key %X status %02X\n",err,c);
|
||||
} else {
|
||||
printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", ccb[0],c);
|
||||
@ -1303,9 +1367,9 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
|
||||
}
|
||||
goto AI_OUT;
|
||||
}
|
||||
n=inb(device, ATA_CYL_HIGH);
|
||||
n=ide_inb(device, ATA_CYL_HIGH);
|
||||
n<<=8;
|
||||
n+=inb(device, ATA_CYL_LOW);
|
||||
n+=ide_inb(device, ATA_CYL_LOW);
|
||||
if(n>buflen) {
|
||||
printf("ERROR, transfer bytes %d requested only %d\n",n,buflen);
|
||||
err=0xff;
|
||||
@ -1324,7 +1388,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
|
||||
/* we transfer shorts */
|
||||
n>>=1;
|
||||
/* ok now decide if it is an in or output */
|
||||
if ((inb(device, ATA_SECT_CNT)&0x02)==0) {
|
||||
if ((ide_inb(device, ATA_SECT_CNT)&0x02)==0) {
|
||||
AT_PRINTF("Write to device\n");
|
||||
output_data_shorts(device,(unsigned short *)buffer,n);
|
||||
} else {
|
||||
@ -1337,7 +1401,7 @@ unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned cha
|
||||
res=0;
|
||||
c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res);
|
||||
if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) {
|
||||
err=(inb(device,ATA_ERROR_REG) >> 4);
|
||||
err=(ide_inb(device,ATA_ERROR_REG) >> 4);
|
||||
AT_PRINTF("atapi_issue 2 returned sense key %X status %X\n",err,c);
|
||||
} else {
|
||||
err = 0;
|
||||
|
@ -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
43
cpu/i386/Makefile
Normal 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
26
cpu/i386/config.mk
Normal 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
62
cpu/i386/cpu.c
Normal 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
583
cpu/i386/interrupts.c
Normal 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
38
cpu/i386/reset.S
Normal 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
460
cpu/i386/serial.c
Normal 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
198
cpu/i386/start.S
Normal 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
112
cpu/i386/start16.S
Normal 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
211
cpu/i386/timer.c
Normal 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
74
doc/README-i386
Normal 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
39
doc/TODO-i386
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#
|
||||
#
|
||||
|
||||
SUBDIRS := jffs2
|
||||
SUBDIRS := jffs2 fdos
|
||||
|
||||
.depend all:
|
||||
@for dir in $(SUBDIRS) ; do \
|
||||
|
49
fs/fdos/Makefile
Normal file
49
fs/fdos/Makefile
Normal 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
195
fs/fdos/dev.c
Normal 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
177
fs/fdos/dos.h
Normal 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
145
fs/fdos/fat.c
Normal 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
175
fs/fdos/fdos.c
Normal 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
117
fs/fdos/fdos.h
Normal 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
120
fs/fdos/fs.c
Normal 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
348
fs/fdos/subdir.c
Normal 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
357
fs/fdos/vfat.c
Normal 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
24
i386_config.mk
Normal 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
384
include/asm-i386/bitops.h
Normal 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 */
|
47
include/asm-i386/byteorder.h
Normal file
47
include/asm-i386/byteorder.h
Normal 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 */
|
60
include/asm-i386/global_data.h
Normal file
60
include/asm-i386/global_data.h
Normal 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
56
include/asm-i386/i8254.h
Normal 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
88
include/asm-i386/i8259.h
Normal 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
47
include/asm-i386/ibmpc.h
Normal 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
|
54
include/asm-i386/ic/ali512x.h
Normal file
54
include/asm-i386/ic/ali512x.h
Normal 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
249
include/asm-i386/ic/sc520.h
Normal 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
207
include/asm-i386/io.h
Normal 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
31
include/asm-i386/pci.h
Normal 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
|
80
include/asm-i386/posix_types.h
Normal file
80
include/asm-i386/posix_types.h
Normal 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
|
53
include/asm-i386/ppcboot-i386.h
Normal file
53
include/asm-i386/ppcboot-i386.h
Normal 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
66
include/asm-i386/ptrace.h
Normal 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
|
31
include/asm-i386/realmode.h
Normal file
31
include/asm-i386/realmode.h
Normal 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
30
include/asm-i386/string.h
Normal 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
51
include/asm-i386/types.h
Normal 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
58
include/asm-i386/u-boot.h
Normal 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
75
include/asm-i386/zimage.h
Normal 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
|
@ -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
55
include/cmd_fdos.h
Normal 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 */
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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 | \
|
||||
|
@ -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 & \
|
||||
|
@ -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
210
include/configs/sc520_cdp.h
Normal 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
41
include/fdc.h
Normal 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
|
@ -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
45
lib_i386/Makefile
Normal 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
443
lib_i386/bios.S
Normal 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
178
lib_i386/bios_setup.c
Normal 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
448
lib_i386/board.c
Normal 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
174
lib_i386/i386_linux.c
Normal 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
442
lib_i386/ic/ali512x.c
Normal 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
348
lib_i386/ic/sc520.c
Normal 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
530
lib_i386/ic/sc520_asm.S
Normal 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
57
lib_i386/pci_type1.c
Normal 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
69
lib_i386/realmode.c
Normal 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
223
lib_i386/realmode_switch.S
Normal 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
276
lib_i386/zimage.c
Normal 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(®s, 0, sizeof(struct pt_regs));
|
||||
regs.xds = (u32)setup_base >> 4;
|
||||
regs.xss = 0x8e00;
|
||||
regs.esp = 0x200;
|
||||
regs.eflags = 0;
|
||||
enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, ®s);
|
||||
}
|
||||
|
||||
|
||||
image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size)
|
||||
{
|
||||
/* There is no way to know the size of a zImage ... *
|
||||
* so we assume that 2MB will be enough for now */
|
||||
#define ZIMAGE_SIZE 0x200000
|
||||
|
||||
/* load a 1MB, the loaded will have to be moved to its final
|
||||
* position again later... */
|
||||
#define ZIMAGE_LOAD 0x100000
|
||||
|
||||
ulong checksum;
|
||||
|
||||
if (KERNEL_MAGIC != *(u16*)(ptr + BOOT_FLAG_OFF)) {
|
||||
/* not a zImage or bzImage */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (-1 == size) {
|
||||
size = ZIMAGE_SIZE;
|
||||
}
|
||||
#if 0
|
||||
checksum = crc32 (0, ptr, size);
|
||||
#else
|
||||
checksum = 0;
|
||||
#endif
|
||||
memset(hdr, 0, sizeof(image_header_t));
|
||||
|
||||
/* Build new header */
|
||||
hdr->ih_magic = htonl(IH_MAGIC);
|
||||
hdr->ih_time = 0;
|
||||
hdr->ih_size = htonl(size);
|
||||
hdr->ih_load = htonl(ZIMAGE_LOAD);
|
||||
hdr->ih_ep = 0;
|
||||
hdr->ih_dcrc = htonl(checksum);
|
||||
hdr->ih_os = IH_OS_LINUX;
|
||||
hdr->ih_arch = IH_CPU_I386;
|
||||
hdr->ih_type = IH_TYPE_KERNEL;
|
||||
hdr->ih_comp = IH_COMP_NONE;
|
||||
|
||||
strncpy((char *)hdr->ih_name, "(none)", IH_NMLEN);
|
||||
|
||||
checksum = crc32(0,(const char *)hdr,sizeof(image_header_t));
|
||||
|
||||
hdr->ih_hcrc = htonl(checksum);
|
||||
|
||||
return hdr;
|
||||
}
|
Loading…
Reference in New Issue
Block a user