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

arch_ide_controller.c

/* $Id: arch_ide_controller.c,v 1.54 2009-02-24 15:12:25 vrsieh Exp $ 
 *
 * Copyright (C) 2005-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#ifdef STATE

struct {
      uint32_t confsp_ide[64];
      unsigned char bmicx[2];
      unsigned char bmisx[2];
      unsigned long bmidtpx[2];

      unsigned long mrpba[2];
      unsigned short count[2];
      unsigned char eot[2];

      unsigned int dma_val[2];

      unsigned long long time;
      int busy;
} NAME;

#endif /* STATE */

#ifdef BEHAVIOR

#include "pci.h" /* FIXME VOSSI */

/* IDE Controller PCI Configuration Registers */
#define C82371AB_IDE_BMIBA    0x20 /* 32 bits */
#define C82371AB_IDE_TIM_PRI  0x40 /* 16 bits */
#define C82371AB_IDE_TIM_SEC  0x42 /* 16 bits */
#define C82371AB_IDE_STIM     0x44 /*  8 bits */
#define C82371AB_IDE_UDMACTL  0x48 /*  8 bits */

/* IDE Controller IO Space Registers */
#define C82371AB_IDE_BMICX    0x00 /*  8 bits */
#define C82371AB_IDE_BMISX    0x02 /*  8 bits */
#define C82371AB_IDE_BMIDTPX  0x04 /* 32 bits */

#define C82371AB_IDE_BMICX_IDE_IOADDR ((uint16_t)((css->NAME.confsp_ide[PCI_BASE_ADDRESS_4>>2] & PCI_BASE_ADDRESS_IO_MASK) & 0xFFFF))

/*
 * Some hints...:
 *
 * Start dma_do if
 * - DMA REQUEST is asserted from drive
 * *and*
 * - DMA is allowed (BMICX bit 1 is set).
 *
 * Stop dma_do if
 * - DMA REQUEST is deasserted
 * *or*
 * - EOT is set *and* COUNT is zero
 */
static void
NAME_(dma_do)(struct cpssp *css, unsigned int ide_nr)
{
      uint32_t val;
      uint16_t word;

      if (css->NAME.eot[ide_nr] && css->NAME.count[ide_nr] == 0) {
            /* Nothing more to transfer. */
            return;
      }

      while (css->NAME.dma_val[ide_nr]
          && ((css->NAME.bmicx[ide_nr] >> 0) & 1)) {
            if (css->NAME.count[ide_nr] == 0) {
                  /*
                   * Read next table entry.
                   */
                  uint32_t w0;
                  uint32_t w1;

                  NAME_(mem_read)(css, css->NAME.bmidtpx[ide_nr], 0xf,
                              &w0);
                  css->NAME.bmidtpx[ide_nr] += sizeof(w0);
                  NAME_(mem_read)(css, css->NAME.bmidtpx[ide_nr], 0xf,
                              &w1);
                  css->NAME.bmidtpx[ide_nr] += sizeof(w1);

                  css->NAME.mrpba[ide_nr] = w0 & 0xfffffffe;
                  css->NAME.count[ide_nr] = w1 & 0xfffe;
                  css->NAME.eot[ide_nr] = (w1 >> 31) & 1;
            }

            /*
             * Transfer data by DMA.
             */
            /* Should read/write chunks of 64 bytes. FIXME VOSSI */
            if (css->NAME.bmicx[ide_nr] & 0x8) {
                  /* DMA READ : Device -> Memory */
                  if (ide_nr == 0) {
                        NAME_(0_inw)(css, &word, 0);
                  } else {
                        NAME_(1_inw)(css, &word, 0);
                  }

                  if (css->NAME.mrpba[ide_nr] & 2) {
                        val = word << 16;
                        NAME_(mem_write)(css,
                              css->NAME.mrpba[ide_nr] & ~2, 0x3 << 2,
                              val);
                  } else {
                        val = word << 0;
                        NAME_(mem_write)(css,
                              css->NAME.mrpba[ide_nr] & ~2, 0x3 << 0,
                              val);
                  }

            } else {
                  /* DMA WRITE: Memory -> Device */
                  if (css->NAME.mrpba[ide_nr] & 2) {
                        NAME_(mem_read)(css,
                              css->NAME.mrpba[ide_nr] & ~2, 0x3 << 2,
                              &val);
                        word = val >> 16;
                  } else {
                        NAME_(mem_read)(css,
                              css->NAME.mrpba[ide_nr] & ~2, 0x3 << 0,
                              &val);
                        word = val >> 0;
                  }

                  if (ide_nr == 0) {
                        NAME_(0_outw)(css, word, 0);
                  } else {
                        NAME_(1_outw)(css, word, 0);
                  }
            }

            css->NAME.mrpba[ide_nr] += 2;
            css->NAME.count[ide_nr] -= 2;

            if (css->NAME.eot[ide_nr] && css->NAME.count[ide_nr] == 0) {
                  /* Clear "Bus Master IDE Active" */
                  css->NAME.bmisx[ide_nr] &= ~(1 << 0);
                  break;
            }
      }
}

static void
NAME_(dmarq_set)(
      struct cpssp *css,
      unsigned int ide_nr,
      unsigned int val
)
{
      assert(ide_nr < 2);

      css->NAME.dma_val[ide_nr] = val;
      if (val == 0) {
            return;
      }

      NAME_(dma_do)(css, ide_nr);
}

static void
NAME_(irqrq_in_set)(
      struct cpssp *css,
      unsigned int ide_nr,
      unsigned int val
)
{
      if (val) {
            css->NAME.bmisx[ide_nr] |= 1 << 2;
      }

      if (ide_nr == 0) {
            NAME_(0_irqrq_out_set)(css, val);
      } else { assert(ide_nr == 1);
            NAME_(1_irqrq_out_set)(css, val);
      }
}

static int
NAME_(responsible)(struct cpssp *css, uint16_t port)
{
      if (! C82371AB_IDE_BMICX_IDE_IOADDR) {
            return 0;
      }

      if (C82371AB_IDE_BMICX_IDE_IOADDR <= port
       && port < C82371AB_IDE_BMICX_IDE_IOADDR + 16) {
            if (! (css->NAME.confsp_ide[PCI_COMMAND >> 2] & PCI_COMMAND_IO)) {
                  return 0;
            }

            return 1;
      }

      return 0;
}

static void
NAME_(outb)(struct cpssp *css, uint8_t val, uint16_t port)
{
      unsigned int nr;

      port -= C82371AB_IDE_BMICX_IDE_IOADDR;
      nr = (port >> 3) & 1;
      port &= ~(1 << 3);

      assert(port < 16);
      assert(nr < 2);

      switch (port) {
      case C82371AB_IDE_BMICX: {
            int start;

            /* Some bits are hardwired to '0'. */
            val &= ~(1 << 7);       /* Reserved */
            val &= ~(1 << 6);       /* Reserved */
            val &= ~(1 << 5);       /* Reserved */
            val &= ~(1 << 4);       /* Reserved */
            val &= ~(1 << 2);       /* Reserved */
            val &= ~(1 << 1);       /* Reserved */

            start = ! ((css->NAME.bmicx[nr] >> 0) & 1) && ((val >> 0) & 1);

            css->NAME.bmicx[nr] = val;

            /* Clear/set "Bus Master IDE Active" bit. */
            css->NAME.bmisx[nr] &= ~(1 << 0);
            css->NAME.bmisx[nr] |= (val >> 0) & 1;

            if (start) {
                  /* Reset DMA state. */
                  css->NAME.count[nr] = 0;
                  css->NAME.eot[nr] = 0;

                  /* Start DMA. */
                  NAME_(dma_do)(css, nr);
            }
            break;
          }
      case C82371AB_IDE_BMISX:
            /* Some bits are hardwired to '0'. */
            val &= ~(1 << 7);       /* Reserved */
            val &= ~(1 << 4);       /* Reserved */
            val &= ~(1 << 3);       /* Reserved */

            /* Some bits are write/clear. */
            if (val & (1 << 2)) {
                  val &= ~(1 << 2);
            } else {
                  val &= ~(1 << 2);
                  val |= css->NAME.bmisx[nr] & (1 << 2);
            }
            if (val & (1 << 1)) {
                  val &= ~(1 << 1);
            } else {
                  val &= ~(1 << 1);
                  val |= css->NAME.bmisx[nr] & (1 << 1);
            }

            /* Some bits are read-only. */
            val &= ~(1 << 0);
            val |= css->NAME.bmisx[nr] & (1 << 0);

            css->NAME.bmisx[nr] = val;
            break;

      case C82371AB_IDE_BMIDTPX ... C82371AB_IDE_BMIDTPX + 3:
            css->NAME.bmidtpx[nr] &= ~(0xff << ((port & 3) * 8));
            css->NAME.bmidtpx[nr] |= (uint32_t) val << ((port & 3) * 8);

            /* Some bits are hardwired to '0'. */
            css->NAME.bmidtpx[nr] &= ~0x03;

            css->NAME.mrpba[nr] = css->NAME.bmidtpx[nr];
            break;

      default:
            fprintf(stderr, "WARNING: 82371AB (IDE): port=0x%02x, val=%02x\n",
                        (nr << 3) | port, val);
            break;
      }
};

static int
NAME_(iow)(void *_css, uint32_t port, unsigned int bs, uint32_t val)
{
      struct cpssp *css = (struct cpssp *) _css;

      if (port == 0x01f0 && bs == (0xf << 0)) {
            NAME_(0_outw)(css, val >> 0, (port & 7) + 0);
            NAME_(0_outw)(css, val >> 16, (port & 7) + 0);
            return 0;
      } else if (port == 0x01f0 && bs == (3 << 0)) {
            NAME_(0_outw)(css, val, (port & 7) + 0);
            return 0;
      } else if (port == 0x01f0 && bs == (1 << 1)) {
            NAME_(0_outw)(css, val >> 8, (port & 7) + 1);
            return 0;
      } else if (port == 0x01f0 && bs == (1 << 2)) {
            NAME_(0_outw)(css, val >> 16, (port & 7) + 2);
            return 0;
      } else if (port == 0x01f0 && bs == (1 << 3)) {
            NAME_(0_outw)(css, val >> 24, (port & 7) + 3);
            return 0;

      } else if (port == 0x01f4 && bs == (1 << 0)) {
            NAME_(0_outw)(css, val >> 0, (port & 7) + 0);
            return 0;
      } else if (port == 0x01f4 && bs == (1 << 1)) {
            NAME_(0_outw)(css, val >> 8, (port & 7) + 1);
            return 0;
      } else if (port == 0x01f4 && bs == (1 << 2)) {
            NAME_(0_outw)(css, val >> 16, (port & 7) + 2);
            return 0;
      } else if (port == 0x01f4 && bs == (1 << 3)) {
            css->NAME.busy = 1;
            NAME_(0_outw)(css, val >> 24, (port & 7) + 3);
            return 0;

      } else if (port == 0x03f4 && bs == (1 << 2)) {
            NAME_(0_outw)(css, val >> 16, 8);
            return 0;

      } else if (port == 0x0170 && bs == (0xf << 0)) {
            NAME_(1_outw)(css, val >> 0, (port & 7) + 0);
            NAME_(1_outw)(css, val >> 16, (port & 7) + 0);
            return 0;
      } else if (port == 0x0170 && bs == (3 << 0)) {
            NAME_(1_outw)(css, val, (port & 7) + 0);
            return 0;
      } else if (port == 0x0170 && bs == (1 << 1)) {
            NAME_(1_outw)(css, val >> 8, (port & 7) + 1);
            return 0;
      } else if (port == 0x0170 && bs == (1 << 2)) {
            NAME_(1_outw)(css, val >> 16, (port & 7) + 2);
            return 0;
      } else if (port == 0x0170 && bs == (1 << 3)) {
            NAME_(1_outw)(css, val >> 24, (port & 7) + 3);
            return 0;

      } else if (port == 0x0174 && bs == (1 << 0)) {
            NAME_(1_outw)(css, val >> 0, (port & 7) + 0);
            return 0;
      } else if (port == 0x0174 && bs == (1 << 1)) {
            NAME_(1_outw)(css, val >> 8, (port & 7) + 1);
            return 0;
      } else if (port == 0x0174 && bs == (1 << 2)) {
            NAME_(1_outw)(css, val >> 16, (port & 7) + 2);
            return 0;
      } else if (port == 0x0174 && bs == (1 << 3)) {
            css->NAME.busy = 1;
            NAME_(1_outw)(css, val >> 24, (port & 7) + 3);
            return 0;

      } else if (port == 0x0374 && bs == (1 << 2)) {
            NAME_(1_outw)(css, val >> 16, 8);
            return 0;

      } else if (NAME_(responsible)(css, port)) {
            if ((bs >> 0) & 1) {
                  NAME_(outb)(css, val >> 0, port + 0);
            }
            if ((bs >> 1) & 1) {
                  NAME_(outb)(css, val >> 8, port + 1);
            }
            if ((bs >> 2) & 1) {
                  NAME_(outb)(css, val >> 16, port + 2);
            }
            if ((bs >> 3) & 1) {
                  NAME_(outb)(css, val >> 24, port + 3);
            }
            return 0;
      }

      return -1;
}

static int
NAME_(iow_info)(
      struct cpssp *css,
      uint32_t port,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t),
      void **csp
)
{
      switch (port) {
      case 0x0170:
      case 0x0174:
      case 0x01f0:
      case 0x01f4:
            *cfp = NAME_(iow);
            *csp = css;
            return 0;
      case 0x0374:
      case 0x03f4:
            if (bs == (1 << 2)) {
                  *cfp = NAME_(iow);
                  *csp = css;
                  return 0;
            }
            break;
      default:
            break;
      }
      return -1;
}

static int
NAME_(inb)(struct cpssp *css, uint8_t *valp, uint16_t port)
{
      unsigned int nr;

      port -= C82371AB_IDE_BMICX_IDE_IOADDR;
      nr = (port >> 3) & 1;
      port &= ~(1 << 3);

      assert(port < 16);
      assert(nr < 2);

      switch (port) {
      case C82371AB_IDE_BMICX:
            *valp = css->NAME.bmicx[nr];
            break;

      case C82371AB_IDE_BMISX:
            *valp = css->NAME.bmisx[nr];
            break;

      case C82371AB_IDE_BMIDTPX ... C82371AB_IDE_BMIDTPX + 3:
            *valp = css->NAME.bmidtpx[nr] >> ((port & 3) * 8);
            break;

      default:
            fprintf(stderr, "BMIDE: READ from port = 0x%02x returning 0x00.\n",
                        (nr << 3) | port);
            *valp = 0x00;
            break;
      }
      return 0;
};

static int
NAME_(ior)(void *_css, uint32_t port, unsigned int bs, uint32_t *valp)
{
      struct cpssp *css = (struct cpssp *) _css;
      uint8_t val8;
      uint16_t val16;

      if (port == 0x01f0 && bs == 0xf) {
            NAME_(0_inw)(css, &val16, 0);
            *valp = val16;
            NAME_(0_inw)(css, &val16, 0);
            *valp |= val16 << 16;
            return 0;
      } else if (port == 0x01f0 && bs == (3 << 0)) {
            NAME_(0_inw)(css, &val16, 0);
            *valp = val16;
            return 0;
      } else if (port == 0x01f0 && bs == (1 << 1)) {
            NAME_(0_inw)(css, &val16, (port & 7) + 1);
            *valp = val16 << 8;
            return 0;
      } else if (port == 0x01f0 && bs == (1 << 2)) {
            NAME_(0_inw)(css, &val16, (port & 7) + 2);
            *valp = val16 << 16;
            return 0;
      } else if (port == 0x01f0 && bs == (1 << 3)) {
            NAME_(0_inw)(css, &val16, (port & 7) + 3);
            *valp = val16 << 24;
            return 0;

      } else if (port == 0x01f4 && bs == (1 << 0)) {
            NAME_(0_inw)(css, &val16, (port & 7) + 0);
            *valp = val16 << 0;
            return 0;
      } else if (port == 0x01f4 && bs == (1 << 1)) {
            NAME_(0_inw)(css, &val16, (port & 7) + 1);
            *valp = val16 << 8;
            return 0;
      } else if (port == 0x01f4 && bs == (1 << 2)) {
            NAME_(0_inw)(css, &val16, (port & 7) + 2);
            *valp = val16 << 16;
            return 0;
      } else if (port == 0x01f4 && bs == (1 << 3)) {
            NAME_(0_inw)(css, &val16, (port & 7) + 3);
            *valp = val16 << 24;
            return 0;

      } else if (port == 0x03f4 && bs == (1 << 2)) {
            NAME_(0_inw)(css, &val16, 8);
            *valp = val16 << 16;
            return 0;

      } else if (port == 0x0170 && bs == 0xf) {
            NAME_(1_inw)(css, &val16, 0);
            *valp = val16;
            NAME_(1_inw)(css, &val16, 0);
            *valp |= val16 << 16;
            return 0;
      } else if (port == 0x0170 && bs == (3 << 0)) {
            NAME_(1_inw)(css, &val16, 0);
            *valp = val16;
            return 0;
      } else if (port == 0x0170 && bs == (1 << 1)) {
            NAME_(1_inw)(css, &val16, (port & 7) + 1);
            *valp = val16 << 8;
            return 0;
      } else if (port == 0x0170 && bs == (1 << 2)) {
            NAME_(1_inw)(css, &val16, (port & 7) + 2);
            *valp = val16 << 16;
            return 0;
      } else if (port == 0x0170 && bs == (1 << 3)) {
            NAME_(1_inw)(css, &val16, (port & 7) + 3);
            *valp = val16 << 24;
            return 0;

      } else if (port == 0x0174 && bs == (1 << 0)) {
            NAME_(1_inw)(css, &val16, (port & 7) + 0);
            *valp = val16 << 0;
            return 0;
      } else if (port == 0x0174 && bs == (1 << 1)) {
            NAME_(1_inw)(css, &val16, (port & 7) + 1);
            *valp = val16 << 8;
            return 0;
      } else if (port == 0x0174 && bs == (1 << 2)) {
            NAME_(1_inw)(css, &val16, (port & 7) + 2);
            *valp = val16 << 16;
            return 0;
      } else if (port == 0x0174 && bs == (1 << 3)) {
            NAME_(1_inw)(css, &val16, (port & 7) + 3);
            *valp = val16 << 24;
            return 0;

      } else if (port == 0x0374 && bs == (1 << 2)) {
            NAME_(1_inw)(css, &val16, 8);
            *valp = val16 << 16;
            return 0;

      } else if (NAME_(responsible)(css, port)) {
            if ((bs >> 0) & 1) {
                  NAME_(inb)(css, &val8, port + 0);
                  *valp &= ~(0xff << 0);
                  *valp |= val8 << 0;
            }
            if ((bs >> 1) & 1) {
                  NAME_(inb)(css, &val8, port + 1);
                  *valp &= ~(0xff << 8);
                  *valp |= val8 << 8;
            }
            if ((bs >> 2) & 1) {
                  NAME_(inb)(css, &val8, port + 2);
                  *valp &= ~(0xff << 16);
                  *valp |= val8 << 16;
            }
            if ((bs >> 3) & 1) {
                  NAME_(inb)(css, &val8, port + 3);
                  *valp &= ~(0xff << 24);
                  *valp |= val8 << 24;
            }
            return 0;
      }

      return -1;
};

static int
NAME_(ior_info)(
      struct cpssp *css,
      uint32_t port,
      unsigned int bs,
      int (**cfp)(void *, uint32_t, unsigned int, uint32_t *),
      void **csp
)
{
      switch (port) {
      case 0x0170:
      case 0x0174:
      case 0x01f0:
      case 0x01f4:
            *cfp = NAME_(ior);
            *csp = css;
            return 0;
      case 0x0374:
      case 0x03f4:
            if (bs == (1 << 2)) {
                  *cfp = NAME_(ior);
                  *csp = css;
                  return 0;
            }
            break;
      default:
            break;
      }
      return -1;
}

static void
NAME_(_creadb)(
      struct cpssp *css,
      uint8_t *valp,
      uint8_t addr
)
{
      *valp = pci_getconfigb(css->NAME.confsp_ide, addr);
}

static void
NAME_(_cwriteb)(
      struct cpssp *css,
      uint8_t val,
      uint8_t addr
)
{
      uint8_t old_val;

      switch (addr) {
      case 0x00 ... 0x01:     /* Vendor Identification */
            goto read_only;

      case 0x02 ... 0x03:     /* Device Identification */
            goto read_only;

      case 0x04:              /* PCI Command (Bit 0-7). */
            /* Some bits are hardwired to '0'/'1'. */
            val &= ~(1 << 7);       /* Reserved */
            val &= ~(1 << 6);       /* Reserved */
            val &= ~(1 << 5);       /* Reserved */
            val &= ~(1 << 4);       /* Memory Write and Invalidate */
            val &= ~(1 << 3);       /* Special Cycle Enable */
            val &= ~(1 << 1);       /* Memory Access */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x05:              /* PCI Command (Bit 8-15). */
            /* Some bits are hardwired to '0'. */
            val &= ~(1 << (15-8));  /* Reserved */
            val &= ~(1 << (14-8));  /* Reserved */
            val &= ~(1 << (13-8));  /* Reserved */
            val &= ~(1 << (12-8));  /* Reserved */
            val &= ~(1 << (11-8));  /* Reserved */
            val &= ~(1 << (10-8));  /* Reserved */
            val &= ~(1 << ( 9-8));  /* Fast Back-to-Back Enable */
            val &= ~(1 << ( 8-8));  /* Reserved */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x06:              /* PCI Device Status (Bit 0-7) */
            /* Some bits are hardwired to '0'/'1'. */
            val |=  (1 << 7);       /* Fast Back to back Capable */
            val &= ~(1 << 6);       /* Reserved */
            val &= ~(1 << 5);       /* Reserved */
            val &= ~(1 << 4);       /* Reserved */
            val &= ~(1 << 3);       /* Reserved */
            val &= ~(1 << 2);       /* Reserved */
            val &= ~(1 << 1);       /* Reserved */
            val &= ~(1 << 0);       /* Reserved */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x07:              /* PCI Device Status (Bit 8-15) */
            /* Some bits are hardwired to '0'/'1'. */
            val &= ~(1 << (15-8));  /* Detected Parity Error */
            val &= ~(1 << (14-8));  /* SERR# Status */
            val &= ~(1 << (10-8));  /* DEVSEL# Timing Status */
            val |=  (1 << ( 9-8));
            val &= ~(1 << ( 8-8));  /* Data Parity Detected */

            /* Some bits are write-clear. */
            old_val = pci_getconfigb(css->NAME.confsp_ide, addr);

            /* Master-Abort Status */
            if ((val & (1 << (13-8)))) {
                  val &= ~(1 << (13-8));
            } else {
                  val &= ~(1 << (13-8));
                  val |= old_val & (1 << (13-8));
            }
            /* Received Target-Abort Status */
            if ((val & (1 << (12-8)))) {
                  val &= ~(1 << (12-8));
            } else {
                  val &= ~(1 << (12-8));
                  val |= old_val & (1 << (12-8));
            }
            /* Signaled Target Abort Status */
            if ((val & (1 << (11-8)))) {
                  val &= ~(1 << (11-8));
            } else {
                  val &= ~(1 << (11-8));
                  val |= old_val & (1 << (11-8));
            }

            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x08:              /* Revision Identification */
            goto read_only;

      case 0x09 ... 0x0b:     /* Class Code */
            goto read_only;

      case 0x0d:              /* Master Latency Timer */
            /* Some bits are hardwired to '0'. */
            val &= ~(1 << 3);
            val &= ~(1 << 2);
            val &= ~(1 << 1);
            val &= ~(1 << 0);

            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x0e:              /* Header Type */

      read_only:
            /*
             * Don't write to read-only registers.
             * We assume a programming error in this case.
             */
            /* Nothing to do. */
            fprintf(stderr, "WARNING: %s: ", "82371AB (IDE)");
            fprintf(stderr, "Writing 0x%02x to read-only register 0x%02x.\n",
                        val, addr);
            break;

      case 0x20 ... 0x21: /* Bus Master Interface Base Address (Bit  0-15) */
            if (addr == 0x20) {
                  /* Clear bits hardwired to '0' */
                  val &= ~(16 - 1);       /* Signal 16 byte I/O space. */
                  /* Set bits hardwired to '1' */
                  val |= 1 << 0;          /* Signal I/O space. */
            }
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x22 ... 0x23: /* Bus Master Interface Base Address (Bit 16-31) */
            /* All bits are hardwired to 0. */
            /* Nothing to do. */
            break;

      case 0x40 ... 0x41: /* IDE Timing (Primary) */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x42 ... 0x43: /* IDE Timing (Secondary) */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x44:          /* Slave IDE Timing */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x48:          /* Ultra DMA/33 Control   */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      case 0x4A ... 0x4B: /* Ultra DMA/33 Timing    */
            pci_setconfigb(css->NAME.confsp_ide, addr, val);
            break;

      default:
            if (addr < 0x40) {
                  /*
                   * Writing to reserved config space registers
                   * *below* 0x40 is allowed. Value written is
                   * discarded.
                   */
                  /* Nothing to do... */

            } else {
                  /*
                   * Writing to reserved config space registers
                   * *above* 0x3f is *not* allowed. Programming error.
                   */
                  fprintf(stderr, "WARNING: %s: ", "82371AB (IDE)");
                  fprintf(stderr, "writing 0x%02x to register 0x%02x.\n",
                              val, addr);
            }
            break;
      }
}

static void
NAME_(cread)(
      struct cpssp *css,
      uint8_t addr,
      unsigned int bsel,
      uint32_t *valp
)
{
      uint8_t val;

      assert(/* 0x00 <= addr && addr <= 0xff && */ (addr & 0x3) == 0);
      assert(0x1 <= bsel && bsel <= 0xf);

      *valp = 0;
      if ((bsel >> 0) & 1) {
            NAME_(_creadb)(css, &val, addr + 0);
            *valp |= (uint32_t) val << 0;
      }
      if ((bsel >> 1) & 1) {
            NAME_(_creadb)(css, &val, addr + 1);
            *valp |= (uint32_t) val << 8;
      }
      if ((bsel >> 2) & 1) {
            NAME_(_creadb)(css, &val, addr + 2);
            *valp |= (uint32_t) val << 16;
      }
      if ((bsel >> 3) & 1) {
            NAME_(_creadb)(css, &val, addr + 3);
            *valp |= (uint32_t) val << 24;
      }
}

static void
NAME_(cwrite)(
      struct cpssp *css,
      uint8_t addr,
      unsigned int bsel,
      uint32_t val
)
{
      assert(/* 0x00 <= addr && addr <= 0xff && */ (addr & 0x3) == 0);
      assert(0x1 <= bsel && bsel <= 0xf);

      if ((bsel >> 0) & 1) {
            NAME_(_cwriteb)(css, (val >>  0) & 0xff, addr + 0);
      }
      if ((bsel >> 1) & 1) {
            NAME_(_cwriteb)(css, (val >>  8) & 0xff, addr + 1);
      }
      if ((bsel >> 2) & 1) {
            NAME_(_cwriteb)(css, (val >> 16) & 0xff, addr + 2);
      }
      if ((bsel >> 3) & 1) {
            NAME_(_cwriteb)(css, (val >> 24) & 0xff, addr + 3);
      }
}

static void
NAME_(timer)(void *_css)
{
      struct cpssp *css = (struct cpssp *) _css;

      NAME_(busy_set)(css, css->NAME.busy);
      css->NAME.busy = 0;

      css->NAME.time += TIME_HZ / 2;
      time_call_at(css->NAME.time, NAME_(timer), css);
}

static void
NAME_(reset)(struct cpssp *css)
{
      memset(css->NAME.confsp_ide, 0, sizeof(css->NAME.confsp_ide));
      pci_setconfigw(css->NAME.confsp_ide, PCI_VENDOR_ID, PCI_VENDOR_ID_INTEL);
      pci_setconfigw(css->NAME.confsp_ide, PCI_DEVICE_ID, 0x7111);
      pci_setconfigw(css->NAME.confsp_ide, PCI_COMMAND, 0x0000);
      /* Fast back to back capable */
      pci_setconfigw(css->NAME.confsp_ide, PCI_STATUS, 0x0280);
      /* FIXME? --tg 06:57 04-12-20 */
      pci_setconfigb(css->NAME.confsp_ide, PCI_REVISION_ID, 0x02);

      pci_setconfigb(css->NAME.confsp_ide, PCI_CLASS_PROG, 0x80);
      pci_setconfigw(css->NAME.confsp_ide, PCI_CLASS_DEVICE, PCI_CLASS_STORAGE_IDE);

      pci_setconfigl(css->NAME.confsp_ide,
                  PCI_BASE_ADDRESS_4,
                  PCI_BASE_ADDRESS_SPACE_IO);
      pci_setconfigw(css->NAME.confsp_ide, C82371AB_IDE_TIM_PRI, 0x8000);
      pci_setconfigw(css->NAME.confsp_ide, C82371AB_IDE_TIM_SEC, 0x8000);
}

static void
NAME_(init)(struct cpssp *css)
{
      css->NAME.time = TIME_HZ / 2;
      time_call_at(css->NAME.time, NAME_(timer), css);
}

#endif /* BEHAVIOR */

Generated by  Doxygen 1.6.0   Back to index