Logo Search packages:      
Sourcecode: palo version File versions  Download package

pdc_bootio.c

/* 
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
 */
#include <stddef.h>
#include <asm/pdc.h>
#include "bootloader.h"
#undef PAGE0
#define     PAGE0 ((struct zeropage *)0x00000000)

/*
 * Sequential seekread from boot device.
 * Return -1 if failed, or 0 if successful.
 */
static int pdc_bootdev_read(int fd,
                  char *dest,
                  unsigned int n,
                  unsigned int seek)
{
    int nbytes = 0;
    static unsigned devaddr = 0;

    if (Debug) printf("pdc_bootdev_read(fd:%d, dest:0x%p, n:%u, seek:0x%x) 0x%x\n",
                  fd, dest, n, seek, devaddr);

    if ((unsigned int)dest & 0x3f) {
      printf("\nERROR: Boot device I/O buffer not properly aligned.\n");
      return -1;
    } else if (n % 2048) {
      printf("\nERROR: Boot device read size not a multiple of 2048.\n");
      return -1;
    } else if (seek & 0x80000000) {
      /* an unreliable test */
      printf("Information: Boot device can't seek past 2Gb (ignore next error).\n");
      return -1;
    }

    if (PAGE0->mem_boot.cl_class == CL_RANDOM)
    {
      devaddr = seek;
    }
    else
    {

      /* check for rewind semantic */
      if (seek < devaddr)
      {
          printf("NOTE: pdc_bootdev_read() asked to seek to 0x%x from 0x%x, rewinding...\n", seek, devaddr);
          /* IODC needs devaddr 0 to do a rewind */
          devaddr = 0;
      }

      while (devaddr < seek)
      {
          unsigned nseek = seek - devaddr;
          int count;
          if (nseek > n)
            nseek = n;
          if ((count = pdc_iodc_bootin(devaddr, dest, nseek)) < 0)
          {
              die("pdc_iodc_bootin() died during seekread\r\n");
            while(1);
          }
          devaddr += count;
      }
    }

    while (nbytes < n)
    {
      int count;

      if (Debug) printf("pdc_iodc_bootin(dev:0x%x, buf:0x%p, count:%u)\r\n",
            devaddr, dest+nbytes, n - nbytes);
      count = pdc_iodc_bootin(devaddr, dest + nbytes, n - nbytes);

      if (Debug)
      {
          printf("%d@0x%x ", count, devaddr);
          {
            int i;
            for (i = 0; i < 16; i++)
                printf(" %02x", dest[nbytes + i] & 0xff);
          }
          puts("\n");
      }

      if (count == 0)
      {
          break;
      }
      else if (count > 0)
      {
          if (devaddr >= seek)
          {
            /* normal seekread */
            nbytes += count;
          }
          devaddr += count;
      }
      else
      {
          /* this could happen after a partial good seekread, which will */
          /* essentially be lost right now */
          printf("\nERROR: Read from boot device failed (status = %d).\n",
            count);
          nbytes = -1;
          break;
      }
    }

    return nbytes;
}

static void pdc_bootdev_describe(int fd, int *bufalign,
                            int *blocksize)
{
    if (bufalign != 0)
      *bufalign = 64;

    if (blocksize != 0)
      *blocksize = FW_BLOCKSIZE;
}

/* returns true if OK */
int pdc_bootdev_open()
{
    return fileio_open(pdc_bootdev_describe, pdc_bootdev_read);
}

/* $Id: pdc_bootio.c,v 1.5 2001/05/15 19:23:11 helgaas Exp $ */

Generated by  Doxygen 1.6.0   Back to index