/*-
* Copyright (c) 2008 John Hay. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
__FBSDID("$FreeBSD$");
#include <sys/linker_set.h>
#include <stdarg.h>
#include "lib.h"
#include "cf_ata.h"
struct board_config {
const char *desc;
void (*init)(void);
};
/* set of registered boards */
}; \
static void cf_init(void);
static void cf_clr(void);
#ifdef DEBUG
#else
#endif
const char *
board_init(void)
{
/* XXX pass down redboot board type */
}
/* XXX panic, unknown board type */
return "???";
}
/*
* This should be called just before starting the kernel. This is so
* that one can undo incompatible hardware settings.
*/
void
clr_board(void)
{
cf_clr();
}
/*
* General support functions.
*/
/*
* DELAY should delay for the number of microseconds.
* The idea is that the inner loop should take 1us, so val is the
* number of usecs to delay.
*/
void
{
volatile int sub;
volatile int subsub;
while(sub) {
subsub = 3;
while(subsub)
subsub--;
sub--;
}
}
{
return (((a & 0xff) << 24) | ((a & 0xff00) << 8) |
((a & 0xff0000) >> 8) | ((a & 0xff000000) >> 24));
}
{
}
/*
* uart related funcs
*/
static u_int8_t
{
}
static void
{
}
int
{
c = 0;
delay = 10000;
return c;
}
void
{
delay = 500;
limit = 20;
limit = 40;
}
void
{
if (ch == '\n')
putchar('\r');
}
void
{
while(*str)
}
void
{
}
void
{
while(length) {
putchar(' ');
str++;
length--;
}
}
/*
*
*
*/
struct {
} dskinf;
static void cfenable16(void);
static void cfdisable16(void);
static void cfreset(void);
#ifdef DEBUG
static int cfgetparams(void);
#endif
static void cfprintregs(void);
static void
cf_init(void)
{
#ifdef DEBUG
int rval;
#endif
/* NB: board init routines setup other parts of dskinf */
dskinf.use_stream8 = 0;
/* Setup the CF window */
/* Detect if there is a disk. */
DELAY(1000);
if (status != 0x50)
if (status == 0xff) {
printf("cf_ata0: No disk!\n");
return;
}
cfreset();
if (dskinf.use_stream8) {
}
#ifdef DEBUG
rval = cfgetparams();
if (rval)
return;
#endif
}
static void
cf_clr(void)
{
}
static void
cfenable16(void)
{
DELAY(100);
#if 0
#endif
}
static void
cfdisable16(void)
{
DELAY(100);
#if 0
#endif
}
static u_int8_t
{
return *vp;
}
static void
{
while (length) {
#ifdef DEBUG
if ((length % 16) == 0)
xputchar('\n');
putchar(' ');
}
#endif
lbuf++;
length--;
}
#ifdef DEBUG
xputchar('\n');
#endif
}
static u_int16_t
{
}
static void
{
cfenable16();
while (length--) {
lbuf++;
}
cfdisable16();
}
static void
{
}
#if 0
static void
{
}
#endif
static u_int8_t
{
off &= 0x0f;
return *vp;
}
static void
{
/*
* This is documented in the Intel appnote 302456.
*/
off &= 0x0f;
}
static int
{
tout = 0;
while (tout <= 5000000) {
if (status == 0xff) {
printf("%s: master: no status, reselecting\n",
__func__);
DELAY(1);
}
if (status == 0xff)
return -1;
if (status & CF_S_ERROR) {
printf("%s: error, status 0x%x error 0x%x\n",
}
DPRINTF("%s: status 0x%x mask 0x%x tout %u\n",
return (status & CF_S_ERROR);
}
}
if (tout > 1000) {
tout += 1000;
DELAY(1000);
} else {
tout += 10;
DELAY(10);
}
}
return -1;
}
static int
{
tout = 0;
while (tout <= 5000000) {
if (status == 0xff) {
printf("cfaltwait: master: no status, reselecting\n");
DELAY(1);
}
if (status == 0xff)
return -1;
if (status & CF_S_ERROR)
return (status & CF_S_ERROR);
}
}
if (tout > 1000) {
tout += 1000;
DELAY(1000);
} else {
tout += 10;
DELAY(10);
}
}
return -1;
}
static int
{
if (cfwait(0) < 0) {
printf("cfcmd: timeout\n");
return -1;
}
else
return 0;
}
static void
cfreset(void)
{
DELAY(1);
#ifdef DEBUG
cfprintregs();
#endif
DELAY(10000);
DELAY(10000);
DELAY(3000);
DELAY(1);
break;
DELAY(100);
}
DELAY(1);
cfprintregs();
printf("cfreset: Status stayed busy after reset.\n");
}
}
#ifdef DEBUG
static int
cfgetparams(void)
{
/* Select the drive. */
DELAY(1);
cfcmd(ATA_ATA_IDENTIFY, 0, 0, 0, 0, 0);
printf("cfgetparams: ATA_IDENTIFY failed.\n");
return -1;
}
if (dskinf.use_stream8)
else
cfprintregs();
#if 0
printf("dsk0: sec %x, hd %x, cyl %x, stat %x, err %x\n",
#endif
printf("cfgetparams: ata_params * %x, stat %x\n",
return 0;
}
#endif /* DEBUG */
static void
cfprintregs(void)
{
putstr("cfprintregs: regs error ");
putstr(", count ");
putstr(", sect ");
putstr(", cyl low ");
putstr(", cyl high ");
putstr(", drv head ");
putstr(", status ");
putstr("\n");
}
int
{
source++;
printf("avila_read: 0x%x, sect %d num secs %d\n",
while (length) {
/* cmd, cyl, head, sect, count, feature */
if (dskinf.use_stream8)
else
length--;
source++;
dest += 512;
}
return 0;
}
/*
* Gateworks Avila Support.
*/
static int
{
/*
* Redboot only configure the chip selects that are needed, so
* use that to figure out if it is an Avila or ADI board. The
* Avila boards use CS2 and ADI does not.
*/
return (*cs != 0);
}
static void
avila_init(void)
{
/* Config the serial port. RedBoot should do the rest. */
cf_init();
}
/*
* Gateworks Cambria Support.
*/
static int
{
return cpu_is_ixp43x();
}
static void
cambria_init(void)
{
/* Config the serial port. RedBoot should do the rest. */
cf_init();
}
/*
* Pronghorn Metro Support.
*/
static int
{
/*
* Redboot only configure the chip selects that are needed, so
* use that to figure out if it is an Avila or ADI board. The
* Avila boards use CS2 and ADI does not.
*/
return (*cs == 0);
}
static void
pronghorn_init(void)
{
/* Config the serial port. RedBoot should do the rest. */
cf_init();
}