diff options
Diffstat (limited to 'qemu/roms/openhackware/src/bloc.c')
-rw-r--r-- | qemu/roms/openhackware/src/bloc.c | 1258 |
1 files changed, 0 insertions, 1258 deletions
diff --git a/qemu/roms/openhackware/src/bloc.c b/qemu/roms/openhackware/src/bloc.c deleted file mode 100644 index b171ed6e3..000000000 --- a/qemu/roms/openhackware/src/bloc.c +++ /dev/null @@ -1,1258 +0,0 @@ -/* - * <bloc.c> - * - * Open Hack'Ware BIOS bloc devices management - * - * Copyright (c) 2004-2005 Jocelyn Mayer - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License V2 - * as published by the Free Software Foundation - * - * 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 <stdlib.h> -#include <stdio.h> -#include "bios.h" - -#undef DPRINTF -#define DPRINTF(fmt, args...) do { } while (0) - -struct bloc_device_t { - int device; - /* Hardware */ - uint32_t io_base; - int drv; - /* Geometry */ - int heads; - int trks; - int sects; - int seclen; - /* Position */ - int bloc; - int vbloc; - int vpos; - /* Access */ - int (*init)(bloc_device_t *bd, int device); - int (*read_sector)(bloc_device_t *bd, void *buffer, int secnum); - int (*ioctl)(bloc_device_t *bd, int func, void *args); - /* buffer */ - char *buffer; - /* Private data */ - int tmp; - void *private; -#ifdef USE_OPENFIRMWARE - void *OF_private; -#endif - /* Partitions */ - part_t *parts, *bparts; - part_t *boot_part; - int bpartnum; - /* Chain */ - bloc_device_t *next; -}; - -static bloc_device_t *bd_list; - -static int fdc_initialize (bloc_device_t *bd, int device); -static int fdc_read_sector (bloc_device_t *bd, void *buffer, int secnum); - -static int ide_initialize (bloc_device_t *bd, int device); -static int ide_read_sector (bloc_device_t *bd, void *buffer, int secnum); -static int ide_reset (bloc_device_t *bd); - -static int mem_initialize (bloc_device_t *bd, int device); -static int mem_read_sector (bloc_device_t *bd, void *buffer, int secnum); -static int mem_ioctl (bloc_device_t *bd, int func, void *args); - -bloc_device_t *bd_open (int device) -{ - bloc_device_t *bd; - int num; - - bd = bd_get(device); - if (bd != NULL) - return bd; - bd = malloc(sizeof(bloc_device_t)); - if (bd == NULL) - return NULL; - bd->ioctl = NULL; - switch (device) { - case 'a': - num = 0; - bd->init = &fdc_initialize; - bd->read_sector = &fdc_read_sector; - break; - case 'b': - num = 1; - bd->init = &fdc_initialize; - bd->read_sector = &fdc_read_sector; - break; - case 'c': - num = 0; - bd->init = &ide_initialize; - bd->read_sector = &ide_read_sector; - break; - case 'd': - num = 1; - bd->init = &ide_initialize; - bd->read_sector = &ide_read_sector; - break; - case 'e': - num = 2; - bd->init = &ide_initialize; - bd->read_sector = &ide_read_sector; - break; - case 'f': - num = 3; - bd->init = &ide_initialize; - bd->read_sector = &ide_read_sector; - break; - case 'm': - num = 0; - bd->init = &mem_initialize; - bd->read_sector = &mem_read_sector; - bd->ioctl = &mem_ioctl; - break; - default: - return NULL; - } - bd->bloc = -1; - if ((*bd->init)(bd, num) < 0) { - free(bd); - return NULL; - } - bd->buffer = malloc(bd->seclen); - if (bd->buffer == NULL) { - free(bd); - return NULL; - } - bd->device = device; - - return bd; -} - -int bd_seek (bloc_device_t *bd, uint32_t bloc, uint32_t pos) -{ - uint32_t maxbloc; - - maxbloc = bd_maxbloc(bd); - if (bloc > maxbloc) { - DPRINTF("%p bloc: %d maxbloc: %d C: %d H: %d S: %d\n", - bd, bloc, maxbloc, bd->trks, bd->heads, bd->sects); - return -1; - } - bd->vbloc = bloc; - bd->vpos = pos; - DPRINTF("%s: %p %08x %08x %08x %08x %08x\n", __func__, bd, bloc, pos, - bd->bloc, bd->vbloc, bd->vpos); - - return 0; -} - -int bd_read (bloc_device_t *bd, void *buffer, int len) -{ - int clen, total; - - for (total = 0; len > 0; total += clen) { - if (bd->vbloc != bd->bloc) { - /* Do physical seek */ -#if 0 - DPRINTF("Read sector %d\n", bd->vbloc); -#endif - if ((*bd->read_sector)(bd, bd->buffer, bd->vbloc) < 0) { - printf("Error reading bloc %d\n", bd->vbloc); - return -1; - } - bd->bloc = bd->vbloc; - } - clen = bd->seclen - bd->vpos; - if (clen > len) - clen = len; - memcpy(buffer, bd->buffer + bd->vpos, clen); -#if 0 - DPRINTF("%s: %p copy %d bytes (%08x %08x %08x) %08x %08x %08x %08x\n", - __func__, bd, clen, bd->bloc, bd->vbloc, bd->vpos, - ((uint32_t *)buffer)[0], ((uint32_t *)buffer)[1], - ((uint32_t *)buffer)[2], ((uint32_t *)buffer)[3]); -#endif - bd->vpos += clen; - if (bd->vpos == bd->seclen) { - bd->vbloc++; - bd->vpos = 0; - } - buffer += clen; - len -= clen; - } - - return total; -} - -int bd_write (unused bloc_device_t *bd, - unused const void *buffer, unused int len) -{ - return -1; -} - -int bd_ioctl (bloc_device_t *bd, int func, void *args) -{ - if (bd->ioctl == NULL) - return -1; - - return (*bd->ioctl)(bd, func, args); -} - -void bd_close (unused bloc_device_t *bd) -{ -} - -void bd_reset_all(void) -{ - bloc_device_t *bd; - for (bd = bd_list; bd != NULL; bd = bd->next) { - if (bd->init == &ide_initialize) { - /* reset IDE drive because Darwin wants all IDE devices to be reset */ - ide_reset(bd); - } - } -} - -uint32_t bd_seclen (bloc_device_t *bd) -{ - return bd->seclen; -} - -uint32_t bd_maxbloc (bloc_device_t *bd) -{ - return bd_CHS2sect(bd, bd->trks, 0, 1); -} - -/* XXX: to be suppressed */ -void bd_set_boot_part (bloc_device_t *bd, part_t *partition, int partnum) -{ - dprintf("%s: part %p (%p) %d\n", __func__, partition, bd->boot_part, partnum); - if (bd->boot_part == NULL) { - bd->boot_part = partition; - bd->bpartnum = partnum; - } -} - -part_t **_bd_parts (bloc_device_t *bd) -{ - return &bd->parts; -} - -part_t **_bd_bparts (bloc_device_t *bd) -{ - return &bd->bparts; -} - -void bd_set_boot_device (bloc_device_t *bd) -{ -#if defined (USE_OPENFIRMWARE) - OF_blockdev_set_boot_device(bd->OF_private, bd->bpartnum, "\\\\ofwboot"); -#endif -} - -part_t *bd_probe (int boot_device) -{ - char devices[] = { /*'a', 'b',*/ 'c', 'd', 'e', 'f', 'm', '\0', }; - bloc_device_t *bd, **cur; - part_t *boot_part, *tmp; - int i, force_raw; - - boot_part = NULL; - /* Probe bloc devices */ - for (i = 0; devices[i] != '\0'; i++) { - if (devices[i] == 'm' && boot_device != 'm') - break; - bd = bd_open(devices[i]); - if (bd != NULL) { - DPRINTF("New bloc device %c: %p\n", devices[i], bd); - for (cur = &bd_list; *cur != NULL; cur = &(*cur)->next) - continue; - *cur = bd; - } else { - DPRINTF("No bloc device %c\n", devices[i]); - } - } - /* Probe partitions for each bloc device found */ - for (bd = bd_list; bd != NULL; bd = bd->next) { - dprintf("Probe partitions for device %c\n", bd->device); - if (bd->device == 'm') - force_raw = 1; - else - force_raw = 0; - tmp = part_probe(bd, force_raw); - if (boot_device == bd->device) { - boot_part = tmp; - bd_set_boot_device(bd); - } - } - - return boot_part; -} - -bloc_device_t *bd_get (int device) -{ - bloc_device_t *cur; - - for (cur = bd_list; cur != NULL; cur = cur->next) { - if (cur->device == device) { - DPRINTF("%s: found device %c: %p\n", __func__, device, cur); - return cur; - } - } - - return NULL; -} - -void bd_put (unused bloc_device_t *bd) -{ -} - -void bd_sect2CHS (bloc_device_t *bd, uint32_t secnum, - int *cyl, int *head, int *sect) -{ - uint32_t tmp; - - tmp = secnum / bd->sects; - *sect = secnum - (tmp * bd->sects) + 1; - *cyl = tmp / bd->heads; - *head = tmp - (*cyl * bd->heads); -} - -uint32_t bd_CHS2sect (bloc_device_t *bd, - int cyl, int head, int sect) -{ - return (((cyl * bd->heads) + head) * bd->sects) + sect - 1; -} - -/* Floppy driver */ -#define FDC_OUT_BASE (0x03F0) -#define FDC_DOR_PORT (FDC_OUT_BASE + 0x0002) -#define FDC_TAPE_PORT (FDC_OUT_BASE + 0x0003) -#define FDC_MAIN_STATUS (FDC_OUT_BASE + 0x0004) -#define FDC_WRITE_PORT (FDC_OUT_BASE + 0x0005) -#define FDC_READ_PORT (FDC_OUT_BASE + 0x0005) - -static int fdc_read_data (uint8_t *addr, int len) -{ - uint8_t status; - int i; - - for (i = 0; i < len; i++) { - status = inb(FDC_MAIN_STATUS); - if ((status & 0xD0) != 0xD0) { -#if 0 - ERROR("fdc_read_data: read data status != READ_DATA: %0x\n", - status); -#endif - return -1; - } - addr[i] = inb(FDC_READ_PORT); - } - - return 0; -} - -static inline int fdc_write_cmd (uint8_t cmd) -{ - uint8_t status; - - status = inb(FDC_MAIN_STATUS); - if ((status & 0xC0) != 0x80) { -#if 0 - ERROR("fdc_write_cmd: read data status != WRITE_CMD: %0x\n", - status); -#endif - return -1; - } - outb(FDC_WRITE_PORT, cmd); - - return 0; -} - -static int fdc_reset (void) -{ - uint8_t dor; - - dor = inb(FDC_DOR_PORT); - /* Stop motors & enter reset */ - dor &= ~0x34; - outb(FDC_DOR_PORT, dor); - usleep(1000); - /* leave reset state */ - dor |= 0x04; - outb(FDC_DOR_PORT, dor); - usleep(1000); - - return 0; -} - -static int fdc_recalibrate (int drv) -{ - uint8_t data[2]; - - if (drv == 0) - data[0] = 0; - else - data[0] = 1; - if (fdc_write_cmd(0x07) < 0) { - ERROR("fdc_recalibrate != WRITE_CMD\n"); - return -1; - } - if (fdc_write_cmd(data[0]) < 0) { - ERROR("fdc_recalibrate data\n"); - return -1; - } - /* Wait for drive to go out of busy state */ - while ((inb(FDC_MAIN_STATUS) & 0x0F) != 0x00) - continue; - /* Check command status */ - if (fdc_write_cmd(0x08) < 0) { - ERROR("fdc_recalibrate != SENSE_INTERRUPT_STATUS\n"); - return -1; - } - data[0] = inb(FDC_READ_PORT); - data[1] = inb(FDC_READ_PORT); - if (data[0] & 0xD0) { - /* recalibrate / seek failed */ - return -1; - } - /* Status should be WRITE_CMD right now */ - if ((inb(FDC_MAIN_STATUS) & 0xD0) != 0x80) { - ERROR("fdc_recalibrate status\n"); - return -1; - } - - return 0; -} - -static int fdc_start_read (int drv, uint8_t hd, uint8_t trk, uint8_t sect, - int mt) -{ - uint8_t fdc_cmd[9], status; - int i; - - fdc_cmd[0] = 0x66; - if (mt) - fdc_cmd[0] |= 0x80; - fdc_cmd[1] = 0x00; - if (hd) - fdc_cmd[1] |= 0x04; - if (drv) - fdc_cmd[1] |= 0x01; - fdc_cmd[2] = trk; - fdc_cmd[3] = hd; - fdc_cmd[4] = sect; - fdc_cmd[5] = 0x02; - fdc_cmd[6] = 0x12; - fdc_cmd[7] = 0x00; - fdc_cmd[8] = 0x00; - for (i = 0; i < (int)sizeof(fdc_cmd); i++) { - status = inb(FDC_MAIN_STATUS); - if ((status & 0xC0) != 0x80) { - ERROR("fdc_start_read: write command status != WRITE_CMD: %0x\n", - status); - return -1; - } - outb(FDC_WRITE_PORT, fdc_cmd[i]); - } - status = inb(FDC_MAIN_STATUS); - if ((status & 0xD0) != 0xD0) { - ERROR("fdc_read_sector: status != READ_DATA: %0x\n", status); - return -1; - } - - return 0; -} - -/* FDC driver entry points */ -static int fdc_initialize (bloc_device_t *bd, int device) -{ - uint8_t fifo[10]; -#if 0 - uint32_t tape; -#endif - int status; - - if (device > 1) - return -1; - DPRINTF("Init FDC drive %d\n", device); - /* Manage 1.44 MB disks only, for now */ - bd->drv = device; - bd->heads = 2; - bd->trks = 80; - bd->sects = 18; - bd->seclen = 512; - bd->tmp = -1; - fdc_reset(); - /* Dump registers */ - if (fdc_write_cmd(0x0E) < 0) { -#if 0 - ERROR("fdc_reset: DUMP_REGISTER != WRITE_CMD\n"); -#endif - return -1; - } - if (fdc_read_data(fifo, 10) < 0) { - ERROR("fdc_reset: DUMP_REGISTER data\n"); - return -1; - } - /* SPECIFY: be sure we're not in DMA mode */ - if (fdc_write_cmd(0x03) < 0) { - ERROR("fdc_reset: SPECIFY != WRITE_CMD\n"); - return -1; - } - if (fdc_write_cmd(fifo[4]) < 0 || fdc_write_cmd(fifo[5] | 0x01)) { - ERROR("fdc_reset: SPECIFY data\n"); - return -1; - } - /* Status should be WRITE_CMD right now */ - status = inb(FDC_MAIN_STATUS); - if ((status & 0xD0) != 0x80) { - ERROR("fdc_initialise: read data status != WRITE_CMD: %0x\n", - status); - return -1; - } - /* RECALIBRATE */ - if (fdc_recalibrate(device) < 0) { - printf("fd%c: no floppy inserted\n", 'a' + device); - return -1; - } - printf("fd%c initialized\n", 'a' + device); - - return 0; -} - -static int fdc_read_sector (bloc_device_t *bd, void *buffer, int secnum) -{ - int head, cyl, sect; - int need_restart; - -#if DEBUG_BIOS > 1 - printf("Read fdc sector: %d at: %0x\n", secnum, (uint32_t)buffer); - bd_sect2CHS(bd, secnum, &cyl, &head, §); - printf("cur: %d hd: %d trk: %d sect: %d\n", bd->bloc, head, cyl, sect); -#endif - if (secnum != bd->tmp) { - if (fdc_reset() < 0 || fdc_recalibrate(bd->drv) < 0) - return -1; - need_restart = 1; - } else { - need_restart = 0; - } - bd_sect2CHS(bd, secnum, &cyl, &head, §); - if (need_restart == 1 || (head == 0 && sect == 1)) { - if (need_restart == 0) { - /* Read the status */ - uint8_t tmp[7]; - - while (fdc_read_data(tmp, 1) == 0) - continue; - } -#if !defined (DEBUG_BIOS) - printf("."); -#endif - if (fdc_start_read(bd->drv, head, cyl, sect, 1) < 0) - return -1; - bd->bloc = secnum; - bd->tmp = secnum; - } - if (fdc_read_data(buffer, bd->seclen) < 0) - return -1; - bd->tmp++; - - return bd->seclen; -} - -/* SCSI subset */ -/* SPC: primary commands, common to all devices */ -static int spc_inquiry_req (void *buffer, int maxlen) -{ - uint8_t *p; - - p = buffer; - p[0] = 0x12; - /* No page code */ - p[1] = 0x00; - p[2] = 0x00; - p[3] = maxlen >> 8; - p[4] = maxlen; - p[5] = 0x00; - - return 6; -} - -static int spc_inquiry_treat (void *buffer, int len) -{ - const uint8_t *p; - - if (len < 36) - return -1; - p = buffer; - if ((p[0] >> 5) != 0) { - ERROR("Logical unit not ready\n"); - return -1; - } - - return p[0] & 0x1F; -} - -static int spc_test_unit_ready_req (void *buffer) -{ - uint8_t *p; - - p = buffer; - p[0] = 0x00; - p[1] = 0x00; - p[2] = 0x00; - p[3] = 0x00; - p[4] = 0x00; - p[5] = 0x00; - - return 6; -} - -/* MMC: multimedia commands */ -static int mmc_read_capacity_req (void *buffer) -{ - uint8_t *p; - - p = buffer; - p[0] = 0x25; - p[1] = 0x00; - p[2] = 0x00; - p[3] = 0x00; - p[4] = 0x00; - p[5] = 0x00; - p[6] = 0x00; - p[7] = 0x00; - p[8] = 0x00; - p[9] = 0x00; - - return 10; -} - -static int mmc_read_capacity_treat (uint32_t *size, uint32_t *ssize, - const void *buffer, int len) -{ - const uint8_t *p; - - if (len != 8) - return -1; - p = buffer; - /* Only handle CDROM address mode for now */ - *size = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) + 1; - *ssize = ((p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]); - - return 0; -} - -static int mmc_read12_req (void *buffer, uint32_t LBA, uint32_t size) -{ - uint8_t *p; - - p = buffer; - p[0] = 0xA8; - p[1] = 0x00; - p[2] = LBA >> 24; - p[3] = LBA >> 16; - p[4] = LBA >> 8; - p[5] = LBA; - p[6] = size >> 24; - p[7] = size >> 16; - p[8] = size >> 8; - p[9] = size; - p[10] = 0x00; - p[11] = 0x00; - - return 12; -} - -/* IDE disk driver */ -static uint32_t ide_base[2] = { 0x1F0, 0x170, }; -static uint32_t ide_base2[2] = { 0x3F6, 0x376, }; - -typedef struct ide_ops_t { - uint8_t (*port_read)(bloc_device_t *bd, int port); - void (*port_write)(bloc_device_t *bd, int port, uint8_t value); - uint32_t (*data_readl)(bloc_device_t *bd); - void (*data_writel)(bloc_device_t *bd, uint32_t val); - void (*control_write)(bloc_device_t *bd, uint32_t val); - uint32_t base[4]; -#ifdef USE_OPENFIRMWARE - void *OF_private[2]; -#endif -} ide_ops_t; - -/* IDE ISA access */ -static uint8_t ide_isa_port_read (bloc_device_t *bd, int port) -{ - return inb(bd->io_base + port); -} - -static void ide_isa_port_write (bloc_device_t *bd, int port, uint8_t value) -{ - outb(bd->io_base + port, value); -} - -static uint32_t ide_isa_data_readl (bloc_device_t *bd) -{ - return inl(bd->io_base); -} - -static void ide_isa_data_writel (bloc_device_t *bd, uint32_t val) -{ - return outl(bd->io_base, val); -} - -static void ide_isa_control_write (bloc_device_t *bd, uint32_t val) -{ - outb(bd->tmp, val); -} - -static ide_ops_t ide_isa_ops = { - &ide_isa_port_read, - &ide_isa_port_write, - &ide_isa_data_readl, - &ide_isa_data_writel, - &ide_isa_control_write, - { 0, }, -#ifdef USE_OPENFIRMWARE - { NULL, }, -#endif -}; - -static ide_ops_t *ide_pci_ops; - -/* IDE PCI access for pc */ -static uint8_t ide_pci_port_read (bloc_device_t *bd, int port) -{ - uint8_t value; - value = inb(bd->io_base + port); - return value; -} - -static void ide_pci_port_write (bloc_device_t *bd, int port, uint8_t value) -{ - outb(bd->io_base + port, value); -} - -static uint32_t ide_pci_data_readl (bloc_device_t *bd) -{ - return inl(bd->io_base); -} - -static void ide_pci_data_writel (bloc_device_t *bd, uint32_t val) -{ - outl(bd->io_base, val); -} - -static void ide_pci_control_write (bloc_device_t *bd, uint32_t val) -{ - outb(bd->tmp + 2, val); -} - -static ide_ops_t ide_pci_pc_ops = { - &ide_pci_port_read, - &ide_pci_port_write, - &ide_pci_data_readl, - &ide_pci_data_writel, - &ide_pci_control_write, - { 0, }, -#ifdef USE_OPENFIRMWARE - { NULL, }, -#endif -}; - -void ide_pci_pc_register (uint32_t io_base0, uint32_t io_base1, - uint32_t io_base2, uint32_t io_base3, - void *OF_private0, void *OF_private1) -{ - if (ide_pci_ops == NULL) { - ide_pci_ops = malloc(sizeof(ide_ops_t)); - if (ide_pci_ops == NULL) - return; - memcpy(ide_pci_ops, &ide_pci_pc_ops, sizeof(ide_ops_t)); - } - if ((io_base0 != 0 || io_base1 != 0) && - ide_pci_ops->base[0] == 0 && ide_pci_ops->base[2] == 0) { - ide_pci_ops->base[0] = io_base0; - ide_pci_ops->base[2] = io_base1; -#ifdef USE_OPENFIRMWARE - ide_pci_ops->OF_private[0] = OF_private0; -#endif - } - if ((io_base2 != 0 || io_base3 != 0) && - ide_pci_ops->base[1] == 0 && ide_pci_ops->base[3] == 0) { - ide_pci_ops->base[1] = io_base2; - ide_pci_ops->base[3] = io_base3; -#ifdef USE_OPENFIRMWARE - ide_pci_ops->OF_private[1] = OF_private1; -#endif - } -} - -/* IDE PCI access for pmac */ -static uint8_t ide_pmac_port_read (bloc_device_t *bd, int port) -{ - uint32_t addr; - - if (port != 8) - addr = bd->io_base + (port << 4); - else - addr = bd->io_base + 0x160; - eieio(); - - return *((uint8_t *)addr); -} - -static void ide_pmac_port_write (bloc_device_t *bd, int port, uint8_t value) -{ - uint32_t addr; - - if (port != 8) - addr = bd->io_base + (port << 4); - else - addr = bd->io_base + 0x160; - *((uint8_t *)addr) = value; - eieio(); -} - -static uint32_t ide_pmac_data_readl (bloc_device_t *bd) -{ - eieio(); - return ldswap32((uint32_t *)bd->io_base); - // return *((uint32_t *)bd->io_base); -} - -static void ide_pmac_data_writel (bloc_device_t *bd, uint32_t val) -{ - // *((uint32_t *)bd->io_base) = val; - stswap32((uint32_t *)bd->io_base, val); - eieio(); -} - -static void ide_pmac_control_write (bloc_device_t *bd, uint32_t val) -{ - ide_pmac_port_write(bd, 8, val); -} - -static ide_ops_t ide_pmac_ops = { - &ide_pmac_port_read, - &ide_pmac_port_write, - &ide_pmac_data_readl, - &ide_pmac_data_writel, - &ide_pmac_control_write, - { 0, }, -#ifdef USE_OPENFIRMWARE - { NULL, }, -#endif -}; - -void ide_pci_pmac_register (uint32_t io_base0, uint32_t io_base1, - unused void *OF_private) -{ - if (ide_pci_ops == NULL) { - ide_pci_ops = malloc(sizeof(ide_ops_t)); - if (ide_pci_ops == NULL) - return; - memcpy(ide_pci_ops, &ide_pmac_ops, sizeof(ide_ops_t)); - } - if (io_base0 != 0 && ide_pci_ops->base[0] == 0) { - ide_pci_ops->base[0] = io_base0; -#ifdef USE_OPENFIRMWARE - ide_pci_ops->OF_private[0] = OF_private; -#endif - } - if (io_base1 != 0 && ide_pci_ops->base[1] == 0) { - ide_pci_ops->base[1] = io_base1; -#ifdef USE_OPENFIRMWARE - ide_pci_ops->OF_private[1] = OF_private; -#endif - } -} - -static inline uint8_t ide_port_read (bloc_device_t *bd, int port) -{ - ide_ops_t *ops = bd->private; - - return ops->port_read(bd, port); -} - -static inline void ide_port_write (bloc_device_t *bd, int port, uint8_t value) -{ - ide_ops_t *ops = bd->private; - - ops->port_write(bd, port, value); -} - -static inline uint32_t ide_data_readl (bloc_device_t *bd) -{ - ide_ops_t *ops = bd->private; - - return ops->data_readl(bd); -} - -static inline void ide_data_writel (bloc_device_t *bd, uint32_t val) -{ - ide_ops_t *ops = bd->private; - - return ops->data_writel(bd, val); -} - -static inline void ide_control_write (bloc_device_t *bd, uint32_t val) -{ - ide_ops_t *ops = bd->private; - - return ops->control_write(bd, val); -} - -static int ide_reset (bloc_device_t *bd) -{ - int status, is_cdrom, lcyl; - - ide_control_write(bd, 0x04); - status = ide_port_read(bd, 0x07); - if (status != 0x90) { - return -1; - } - ide_control_write(bd, 0x00); - if (bd->drv == 0) - ide_port_write(bd, 0x06, 0xa0); - else - ide_port_write(bd, 0x06, 0xb0); - - lcyl = ide_port_read(bd, 0x04); - switch (lcyl) { - case 0x00: - /* IDE drive */ - is_cdrom = 0; - break; - case 0x14: - /* ATAPI device */ - is_cdrom = 1; - break; - default: - return -1; - } - - return is_cdrom; -} - -static void atapi_pad_req (void *buffer, int len); -static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer, - int maxlen); -static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum); - -static int ide_initialize (bloc_device_t *bd, int device) -{ -#ifdef USE_OPENFIRMWARE - void *OF_parent; -#endif - const unsigned char *devname, *devtype, *alias; - uint32_t atapi_buffer[9]; - uint32_t size; - int status, base, is_cdrom, len, i; - - if (device > 1) - base = 1; - else - base = 0; - if (ide_pci_ops != NULL) { - bd->private = ide_pci_ops; - bd->io_base = ide_pci_ops->base[base]; - bd->tmp = ide_pci_ops->base[2 + base]; - if (bd->io_base == 0x00000000 || bd->io_base == 0xFFFFFFFF) { - ERROR("No IDE drive %c\n", device); - return -1; - } - } else { - bd->private = &ide_isa_ops; - bd->io_base = ide_base[base]; - bd->tmp = ide_base2[base]; - } - bd->drv = device & 1; - DPRINTF("Init IDE drive %d-%d (%d)\n", base, bd->drv, device); - is_cdrom = ide_reset(bd); - printf("ide%d: drive %d: ", - (device >> 1), bd->drv); - switch(is_cdrom) { - case 0: - printf("Hard Disk\n"); - devname = "disk"; - devtype = "hd"; - alias = "hd"; - break; - case 1: - printf("CD-ROM\n"); - devname = "cdrom"; - devtype = "cdrom"; - alias = "cd"; - break; - default: - printf("none\n"); - devname = NULL; - devtype = NULL; - alias = NULL; - break; - } - if (is_cdrom < 0) - return -1; -#ifdef USE_OPENFIRMWARE - /* Register disk into OF tree */ - OF_parent = ide_pci_ops->OF_private[base]; - if (OF_parent != NULL) { - bd->OF_private = OF_blockdev_register(OF_parent, bd, devtype, - devname, bd->drv, alias); - } -#endif - /* Select drive */ - if (bd->drv == 0) - ide_port_write(bd, 0x06, 0x40); - else - ide_port_write(bd, 0x06, 0x50); - /* WIN_DEVICE_RESET */ - ide_port_write(bd, 0x07, 0x08); - status = ide_port_read(bd, 0x07); - if (is_cdrom) { - if (status != 0x00) { - ERROR("WIN_DEVICE_RESET : status %0x != 0x00 (is_cdrom: %d)\n", - status, is_cdrom); - return -1; - } - /* TEST_UNIT_READY */ - DPRINTF("TEST_UNIT_READY\n"); - len = spc_test_unit_ready_req(&atapi_buffer); - atapi_pad_req(&atapi_buffer, len); - ide_port_write(bd, 0x07, 0xA0); - status = ide_port_read(bd, 0x07); - if (status != 0x08) { - ERROR("ATAPI TEST_UNIT_READY : status %0x != 0x08\n", status); - /*return -1;*/ /* fails to boot from cdrom? */ - } - for (i = 0; i < 3; i++) { - ide_data_writel(bd, ldswap32(&atapi_buffer[i])); - } - status = ide_port_read(bd, 0x07); - if (status != 0x40) { - ERROR("ATAPI TEST_UNIT_READY : status %0x != 0x40\n", status); - return -1; - } - /* INQUIRY */ - DPRINTF("INQUIRY\n"); - len = spc_inquiry_req(&atapi_buffer, 36); - atapi_pad_req(&atapi_buffer, len); - atapi_make_req(bd, atapi_buffer, 36); - status = ide_port_read(bd, 0x07); - if (status != 0x48) { - ERROR("ATAPI INQUIRY : status %0x != 0x48\n", status); - return -1; - } - for (i = 0; i < 9; i++) - stswap32(&atapi_buffer[i], ide_data_readl(bd)); - if (spc_inquiry_treat(&atapi_buffer, 36) != 0x05) { - ERROR("Only ATAPI CDROMs are handled for now\n"); - return -1; - } - /* READ_CAPACITY */ - DPRINTF("READ_CAPACITY\n"); - len = mmc_read_capacity_req(&atapi_buffer); - atapi_pad_req(&atapi_buffer, len); - atapi_make_req(bd, atapi_buffer, 8); - status = ide_port_read(bd, 0x07); - if (status != 0x48) { - ERROR("ATAPI READ_CAPACITY : status %0x != 0x48\n", status); - return -1; - } - for (i = 0; i < 2; i++) - stswap32(&atapi_buffer[i], ide_data_readl(bd)); - if (mmc_read_capacity_treat(&size, &bd->seclen, - &atapi_buffer, 8) != 0) { - ERROR("Error retrieving ATAPI CDROM capacity\n"); - return -1; - } - bd->read_sector = &atapi_read_sector; - DPRINTF("ATAPI: size=%d ssize=%d\n", size, bd->seclen); - } else { - if (status != 0x41) { - ERROR("WIN_DEVICE_RESET : status %0x != 0x41 (is_cdrom: %d)\n", - status, is_cdrom); - return -1; - } - /* WIN_READ_NATIVE_MAX */ - ide_port_write(bd, 0x07, 0xF8); - status = ide_port_read(bd, 0x07); - if (status != 0x40) { - ERROR("WIN_READ_NATIVE_MAX : status %0x != 0x40\n", status); - return -1; - } - /* Retrieve parameters */ - size = (ide_port_read(bd, 0x06) & ~0xF0) << 24; - size |= ide_port_read(bd, 0x05) << 16; - size |= ide_port_read(bd, 0x04) << 8; - size |= ide_port_read(bd, 0x03); - bd->seclen = 512; - } - bd->heads = 16; - bd->sects = 64; - bd->trks = (size + (16 * 64 - 1)) >> 10; - - return 0; -} - -static void atapi_pad_req (void *buffer, int len) -{ - uint8_t *p; - - p = buffer; - memset(p + len, 0, 12 - len); -} - -static void atapi_make_req (bloc_device_t *bd, uint32_t *buffer, - int maxlen) -{ - int i; - /* select drive */ - if (bd->drv == 0) - ide_port_write(bd, 0x06, 0x40); - else - ide_port_write(bd, 0x06, 0x50); - ide_port_write(bd, 0x04, maxlen & 0xff); - ide_port_write(bd, 0x05, (maxlen >> 8) & 0xff); - ide_port_write(bd, 0x07, 0xA0); - for (i = 0; i < 3; i++) - ide_data_writel(bd, ldswap32(&buffer[i])); -} - -static int atapi_read_sector (bloc_device_t *bd, void *buffer, int secnum) -{ - uint32_t atapi_buffer[4]; - uint8_t *p; - uint32_t status, value; - int i, len; - - len = mmc_read12_req(atapi_buffer, secnum, 1); - atapi_pad_req(&atapi_buffer, len); - atapi_make_req(bd, atapi_buffer, bd->seclen); - status = ide_port_read(bd, 0x07); - if (status != 0x48) { - ERROR("ATAPI READ12 : status %0x != 0x48\n", status); - return -1; - } - p = buffer; - for (i = 0; i < bd->seclen; i += 4) { - value = ide_data_readl(bd); - *p++ = value; - *p++ = value >> 8; - *p++ = value >> 16; - *p++ = value >> 24; - } - status = ide_port_read(bd, 0x07); - if (status != 0x40) { - ERROR("ATAPI READ12 done : status %0x != 0x48\n", status); - return -1; - } - - return 0; -} - -static int ide_read_sector (bloc_device_t *bd, void *buffer, int secnum) -{ - uint32_t value; - uint8_t *p; - int status; - int i; - - bd->drv &= 1; - // printf("ide_read_sector: drv %d secnum %d buf %p\n", bd->drv, secnum, buffer); - /* select drive & set highest bytes */ - if (bd->drv == 0) - ide_port_write(bd, 0x06, 0x40 | (secnum >> 24)); - else - ide_port_write(bd, 0x06, 0x50 | (secnum >> 24)); - /* Set hcyl */ - ide_port_write(bd, 0x05, secnum >> 16); - /* Set lcyl */ - ide_port_write(bd, 0x04, secnum >> 8); - /* Set sect */ - ide_port_write(bd, 0x03, secnum); - /* Read 1 sector */ - ide_port_write(bd, 0x02, 1); - /* WIN_READ */ - ide_port_write(bd, 0x07, 0x20); - status = ide_port_read(bd, 0x07); - // DPRINTF("ide_read_sector: try %d\n", secnum); - if (status != 0x58) { - ERROR("ide_read_sector: %d status %0x != 0x58\n", secnum, status); - return -1; - } - /* Get data */ - p = buffer; - for (i = 0; i < bd->seclen; i += 4) { - value = ide_data_readl(bd); - *p++ = value; - *p++ = value >> 8; - *p++ = value >> 16; - *p++ = value >> 24; - } - status = ide_port_read(bd, 0x07); - if (status != 0x50) { - ERROR("ide_read_sector 6: status %0x != 0x50\n", status); - return -1; - } - - return bd->seclen; -} - -/* Memory image access driver */ -static int mem_initialize (bloc_device_t *bd, int device) -{ - bd->seclen = 512; - bd->private = NULL; - bd->heads = 1; - bd->sects = 1; - bd->trks = 1; - - return device == 'm'; -} - -static int mem_read_sector (bloc_device_t *bd, void *buffer, int secnum) -{ - if (buffer != (char *)bd->private + (bd->seclen * secnum)) { - memmove(buffer, - (char *)bd->private + (bd->seclen * secnum), bd->seclen); - } - - return bd->seclen; -} - -static int mem_ioctl (bloc_device_t *bd, int func, void *args) -{ - uint32_t *u32; - int ret; - - switch (func) { - case MEM_SET_ADDR: - bd->private = args; - ret = 0; - break; - case MEM_SET_SIZE: - u32 = args; - bd->trks = (*u32 + bd->seclen - 1) / bd->seclen + 1; - default: - ret = -1; - break; - } - - return ret; -} |