Separate ATA code from generic disk code.
authorKevin O'Connor <kevin@koconnor.net>
Wed, 12 Aug 2009 01:59:37 +0000 (21:59 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Wed, 12 Aug 2009 01:59:37 +0000 (21:59 -0400)
Move generic code from ata.c to new file block.c.
Rename atabits.h to ata.h and move ata header definitions from disk.h.
Rename ATA.channels to ATA_channels.
Rename ATA structure to Drives.
Support both CONFIG_DRIVES and CONFIG_ATA options.

13 files changed:
Makefile
src/ata.c
src/ata.h [new file with mode: 0644]
src/atabits.h [deleted file]
src/biosvar.h
src/block.c [new file with mode: 0644]
src/boot.c
src/cdrom.c
src/config.h
src/disk.c
src/disk.h
src/floppy.c
src/post.c

index 37589097295dde049f8512d99561a0320955fb41..2b8d0d23ac97f89f02d782faa08156a3ea7f8202 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ VERSION=pre-0.4.2-$(shell date +"%Y%m%d_%H%M%S")-$(shell hostname)
 OUT=out/
 
 # Source files
-SRCBOTH=output.c util.c floppy.c ata.c misc.c mouse.c kbd.c pci.c \
+SRCBOTH=output.c util.c block.c floppy.c ata.c misc.c mouse.c kbd.c pci.c \
         serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \
         pnpbios.c pirtable.c vgahooks.c pmm.c
 SRC16=$(SRCBOTH) system.c disk.c apm.c pcibios.c font.c
index 5dac4e97e691d0bad4fa0d255d931035e7b11685..49af87f830a050f51c0e009ffd8af2896700584a 100644 (file)
--- a/src/ata.c
+++ b/src/ata.c
@@ -1,6 +1,6 @@
 // Low level ATA disk access
 //
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 // Copyright (C) 2002  MandrakeSoft S.A.
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 #include "pci_regs.h" // PCI_INTERRUPT_LINE
 #include "boot.h" // add_bcv_hd
 #include "disk.h" // struct ata_s
-#include "atabits.h" // ATA_CB_STAT
+#include "ata.h" // ATA_CB_STAT
 
 #define IDE_SECTOR_SIZE 512
 #define CDROM_SECTOR_SIZE 2048
 
 #define IDE_TIMEOUT 32000 //32 seconds max for IDE ops
 
-struct ata_s ATA VAR16_32;
+struct ata_channel_s ATA_channels[CONFIG_MAX_ATA_INTERFACES] VAR16_32;
 
 
 /****************************************************************
@@ -82,11 +82,11 @@ ndelay_await_not_bsy(u16 iobase1)
 static void
 ata_reset(int driveid)
 {
-    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
     u8 channel = ataid / 2;
     u8 slave = ataid % 2;
-    u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
-    u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
+    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
+    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
 
     dprintf(6, "ata_reset driveid=%d\n", driveid);
     // Pulse SRST
@@ -118,7 +118,7 @@ ata_reset(int driveid)
     }
 
     // On a user-reset request, wait for RDY if it is an ATA device.
-    u8 type=GET_GLOBAL(ATA.devices[driveid].type);
+    u8 type=GET_GLOBAL(Drives.drives[driveid].type);
     if (type == DTYPE_ATA)
         status = await_rdy(iobase1);
 
@@ -133,9 +133,9 @@ static int
 isready(int driveid)
 {
     // Read the status from controller
-    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
     u8 channel = ataid / 2;
-    u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
+    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
     u8 status = inb(iobase1 + ATA_CB_STAT);
     return (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY;
 }
@@ -143,6 +143,9 @@ isready(int driveid)
 static int
 process_ata_misc_op(struct disk_op_s *op)
 {
+    if (!CONFIG_ATA)
+        return 0;
+
     switch (op->command) {
     default:
         return 0;
@@ -178,11 +181,11 @@ struct ata_pio_command {
 static int
 send_cmd(int driveid, struct ata_pio_command *cmd)
 {
-    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
     u8 channel = ataid / 2;
     u8 slave = ataid % 2;
-    u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
-    u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
+    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
+    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
 
     // Disable interrupts
     outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
@@ -246,10 +249,10 @@ ata_transfer(struct disk_op_s *op, int iswrite, int blocksize)
     dprintf(16, "ata_transfer id=%d write=%d count=%d bs=%d buf=%p\n"
             , op->driveid, iswrite, op->count, blocksize, op->buf_fl);
 
-    u8 ataid = GET_GLOBAL(ATA.devices[op->driveid].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[op->driveid].cntl_id);
     u8 channel = ataid / 2;
-    u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
-    u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
+    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
+    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
     int count = op->count;
     void *buf_fl = op->buf_fl;
     int status;
@@ -345,6 +348,9 @@ ata_cmd_data(struct disk_op_s *op, int iswrite, int command)
 int
 process_ata_op(struct disk_op_s *op)
 {
+    if (!CONFIG_ATA)
+        return 0;
+
     switch (op->command) {
     case CMD_READ:
         return ata_cmd_data(op, 0, ATA_CMD_READ_SECTORS);
@@ -364,10 +370,10 @@ process_ata_op(struct disk_op_s *op)
 static int
 send_atapi_cmd(int driveid, u8 *cmdbuf, u8 cmdlen, u16 blocksize)
 {
-    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
     u8 channel = ataid / 2;
-    u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
-    u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
+    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
+    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
 
     struct ata_pio_command cmd;
     cmd.sector_count = 0;
@@ -457,111 +463,6 @@ ata_cmd_packet(int driveid, u8 *cmdbuf, u8 cmdlen
 }
 
 
-/****************************************************************
- * Disk geometry translation
- ****************************************************************/
-
-static u8
-get_translation(int driveid)
-{
-    if (! CONFIG_COREBOOT) {
-        // Emulators pass in the translation info via nvram.
-        u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
-        u8 channel = ataid / 2;
-        u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
-        translation >>= 2 * (ataid % 4);
-        translation &= 0x03;
-        return translation;
-    }
-
-    // On COREBOOT, use a heuristic to determine translation type.
-    u16 heads = GET_GLOBAL(ATA.devices[driveid].pchs.heads);
-    u16 cylinders = GET_GLOBAL(ATA.devices[driveid].pchs.cylinders);
-    u16 spt = GET_GLOBAL(ATA.devices[driveid].pchs.spt);
-
-    if (cylinders <= 1024 && heads <= 16 && spt <= 63)
-        return TRANSLATION_NONE;
-    if (cylinders * heads <= 131072)
-        return TRANSLATION_LARGE;
-    return TRANSLATION_LBA;
-}
-
-static void
-setup_translation(int driveid)
-{
-    u8 translation = get_translation(driveid);
-    SET_GLOBAL(ATA.devices[driveid].translation, translation);
-
-    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
-    u8 channel = ataid / 2;
-    u8 slave = ataid % 2;
-    u16 heads = GET_GLOBAL(ATA.devices[driveid].pchs.heads);
-    u16 cylinders = GET_GLOBAL(ATA.devices[driveid].pchs.cylinders);
-    u16 spt = GET_GLOBAL(ATA.devices[driveid].pchs.spt);
-    u64 sectors = GET_GLOBAL(ATA.devices[driveid].sectors);
-
-    dprintf(1, "ata%d-%d: PCHS=%u/%d/%d translation="
-            , channel, slave, cylinders, heads, spt);
-    switch (translation) {
-    case TRANSLATION_NONE:
-        dprintf(1, "none");
-        break;
-    case TRANSLATION_LBA:
-        dprintf(1, "lba");
-        spt = 63;
-        if (sectors > 63*255*1024) {
-            heads = 255;
-            cylinders = 1024;
-            break;
-        }
-        u32 sect = (u32)sectors / 63;
-        heads = sect / 1024;
-        if (heads>128)
-            heads = 255;
-        else if (heads>64)
-            heads = 128;
-        else if (heads>32)
-            heads = 64;
-        else if (heads>16)
-            heads = 32;
-        else
-            heads = 16;
-        cylinders = sect / heads;
-        break;
-    case TRANSLATION_RECHS:
-        dprintf(1, "r-echs");
-        // Take care not to overflow
-        if (heads==16) {
-            if (cylinders>61439)
-                cylinders=61439;
-            heads=15;
-            cylinders = (u16)((u32)(cylinders)*16/15);
-        }
-        // then go through the large bitshift process
-    case TRANSLATION_LARGE:
-        if (translation == TRANSLATION_LARGE)
-            dprintf(1, "large");
-        while (cylinders > 1024) {
-            cylinders >>= 1;
-            heads <<= 1;
-
-            // If we max out the head count
-            if (heads > 127)
-                break;
-        }
-        break;
-    }
-    // clip to 1024 cylinders in lchs
-    if (cylinders > 1024)
-        cylinders = 1024;
-    dprintf(1, " LCHS=%d/%d/%d\n", cylinders, heads, spt);
-
-    SET_GLOBAL(ATA.devices[driveid].lchs.heads, heads);
-    SET_GLOBAL(ATA.devices[driveid].lchs.cylinders, cylinders);
-    SET_GLOBAL(ATA.devices[driveid].lchs.spt, spt);
-}
-
-
 /****************************************************************
  * ATA detect and init
  ****************************************************************/
@@ -586,8 +487,8 @@ extract_identify(int driveid, u16 *buffer)
     dprintf(3, "Identify w0=%x w2=%x\n", buffer[0], buffer[2]);
 
     // Read model name
-    char *model = ATA.devices[driveid].model;
-    int maxsize = ARRAY_SIZE(ATA.devices[driveid].model);
+    char *model = Drives.drives[driveid].model;
+    int maxsize = ARRAY_SIZE(Drives.drives[driveid].model);
     int i;
     for (i=0; i<maxsize/2; i++) {
         u16 v = buffer[27+i];
@@ -601,7 +502,7 @@ extract_identify(int driveid, u16 *buffer)
         model[i] = 0x00;
 
     // Common flags.
-    SET_GLOBAL(ATA.devices[driveid].removable, (buffer[0] & 0x80) ? 1 : 0);
+    SET_GLOBAL(Drives.drives[driveid].removable, (buffer[0] & 0x80) ? 1 : 0);
 }
 
 static int
@@ -621,25 +522,22 @@ init_drive_atapi(int driveid, u16 *buffer)
 
     // Success - setup as ATAPI.
     extract_identify(driveid, buffer);
-    SET_GLOBAL(ATA.devices[driveid].type, DTYPE_ATAPI);
-    SET_GLOBAL(ATA.devices[driveid].blksize, CDROM_SECTOR_SIZE);
-    SET_GLOBAL(ATA.devices[driveid].sectors, (u64)-1);
+    SET_GLOBAL(Drives.drives[driveid].type, DTYPE_ATAPI);
+    SET_GLOBAL(Drives.drives[driveid].blksize, CDROM_SECTOR_SIZE);
+    SET_GLOBAL(Drives.drives[driveid].sectors, (u64)-1);
     u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
 
     // Report drive info to user.
-    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
     u8 channel = ataid / 2;
     u8 slave = ataid % 2;
     printf("ata%d-%d: %s ATAPI-%d %s\n", channel, slave
-           , ATA.devices[driveid].model, extract_version(buffer)
+           , Drives.drives[driveid].model, extract_version(buffer)
            , (iscd ? "CD-Rom/DVD-Rom" : "Device"));
 
     // fill cdidmap
-    if (iscd) {
-        u8 cdcount = GET_GLOBAL(ATA.cdcount);
-        SET_GLOBAL(ATA.idmap[1][cdcount], driveid);
-        SET_GLOBAL(ATA.cdcount, cdcount+1);
-    }
+    if (iscd)
+        map_cd_drive(driveid);
 
     return 0;
 }
@@ -661,28 +559,28 @@ init_drive_ata(int driveid, u16 *buffer)
 
     // Success - setup as ATA.
     extract_identify(driveid, buffer);
-    SET_GLOBAL(ATA.devices[driveid].type, DTYPE_ATA);
-    SET_GLOBAL(ATA.devices[driveid].blksize, IDE_SECTOR_SIZE);
+    SET_GLOBAL(Drives.drives[driveid].type, DTYPE_ATA);
+    SET_GLOBAL(Drives.drives[driveid].blksize, IDE_SECTOR_SIZE);
 
-    SET_GLOBAL(ATA.devices[driveid].pchs.cylinders, buffer[1]);
-    SET_GLOBAL(ATA.devices[driveid].pchs.heads, buffer[3]);
-    SET_GLOBAL(ATA.devices[driveid].pchs.spt, buffer[6]);
+    SET_GLOBAL(Drives.drives[driveid].pchs.cylinders, buffer[1]);
+    SET_GLOBAL(Drives.drives[driveid].pchs.heads, buffer[3]);
+    SET_GLOBAL(Drives.drives[driveid].pchs.spt, buffer[6]);
 
     u64 sectors;
     if (buffer[83] & (1 << 10)) // word 83 - lba48 support
         sectors = *(u64*)&buffer[100]; // word 100-103
     else
         sectors = *(u32*)&buffer[60]; // word 60 and word 61
-    SET_GLOBAL(ATA.devices[driveid].sectors, sectors);
+    SET_GLOBAL(Drives.drives[driveid].sectors, sectors);
 
     // Setup disk geometry translation.
     setup_translation(driveid);
 
     // Report drive info to user.
-    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
     u8 channel = ataid / 2;
     u8 slave = ataid % 2;
-    char *model = ATA.devices[driveid].model;
+    char *model = Drives.drives[driveid].model;
     printf("ata%d-%d: %s ATA-%d Hard-Disk ", channel, slave, model
            , extract_version(buffer));
     u64 sizeinmb = sectors >> 11;
@@ -730,7 +628,7 @@ ata_detect()
         u8 channel = ataid / 2;
         u8 slave = ataid % 2;
 
-        u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
+        u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
         if (!iobase1)
             break;
 
@@ -758,10 +656,10 @@ ata_detect()
             continue;
 
         // Prepare new driveid.
-        if (driveid >= ARRAY_SIZE(ATA.devices))
+        if (driveid >= ARRAY_SIZE(Drives.drives))
             break;
-        memset(&ATA.devices[driveid], 0, sizeof(ATA.devices[0]));
-        ATA.devices[driveid].cntl_id = ataid;
+        memset(&Drives.drives[driveid], 0, sizeof(Drives.drives[0]));
+        Drives.drives[driveid].cntl_id = ataid;
 
         // reset the channel
         if (slave && ataid == last_reset_ataid + 1) {
@@ -810,27 +708,18 @@ ata_detect()
 static void
 ata_init()
 {
-    memset(&ATA, 0, sizeof(ATA));
-
-    // hdidmap and cdidmap init.
-    u8 device;
-    for (device=0; device < CONFIG_MAX_ATA_DEVICES; device++) {
-        SET_GLOBAL(ATA.idmap[0][device], CONFIG_MAX_ATA_DEVICES);
-        SET_GLOBAL(ATA.idmap[1][device], CONFIG_MAX_ATA_DEVICES);
-    }
-
     // Scan PCI bus for ATA adapters
     int count=0;
     int bdf, max;
     foreachpci(bdf, max) {
         if (pci_config_readw(bdf, PCI_CLASS_DEVICE) != PCI_CLASS_STORAGE_IDE)
             continue;
-        if (count >= ARRAY_SIZE(ATA.channels))
+        if (count >= ARRAY_SIZE(ATA_channels))
             break;
 
         u8 irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
-        SET_GLOBAL(ATA.channels[count].irq, irq);
-        SET_GLOBAL(ATA.channels[count].pci_bdf, bdf);
+        SET_GLOBAL(ATA_channels[count].irq, irq);
+        SET_GLOBAL(ATA_channels[count].pci_bdf, bdf);
 
         u8 prog_if = pci_config_readb(bdf, PCI_CLASS_PROG);
         u32 port1, port2;
@@ -842,8 +731,8 @@ ata_init()
             port1 = 0x1f0;
             port2 = 0x3f0;
         }
-        SET_GLOBAL(ATA.channels[count].iobase1, port1);
-        SET_GLOBAL(ATA.channels[count].iobase2, port2);
+        SET_GLOBAL(ATA_channels[count].iobase1, port1);
+        SET_GLOBAL(ATA_channels[count].iobase2, port2);
         dprintf(1, "ATA controller %d at %x/%x (dev %x prog_if %x)\n"
                 , count, port1, port2, bdf, prog_if);
         count++;
@@ -857,14 +746,14 @@ ata_init()
         }
         dprintf(1, "ATA controller %d at %x/%x (dev %x prog_if %x)\n"
                 , count, port1, port2, bdf, prog_if);
-        SET_GLOBAL(ATA.channels[count].iobase1, port1);
-        SET_GLOBAL(ATA.channels[count].iobase2, port2);
+        SET_GLOBAL(ATA_channels[count].iobase1, port1);
+        SET_GLOBAL(ATA_channels[count].iobase2, port2);
         count++;
     }
 }
 
 void
-hard_drive_setup()
+ata_setup()
 {
     if (!CONFIG_ATA)
         return;
@@ -877,68 +766,3 @@ hard_drive_setup()
 
     enable_hwirq(14, entry_76);
 }
-
-
-/****************************************************************
- * Drive mapping
- ****************************************************************/
-
-// Fill in Fixed Disk Parameter Table (located in ebda).
-static void
-fill_fdpt(int driveid)
-{
-    if (driveid > 1)
-        return;
-
-    u16 nlc   = GET_GLOBAL(ATA.devices[driveid].lchs.cylinders);
-    u16 nlh   = GET_GLOBAL(ATA.devices[driveid].lchs.heads);
-    u16 nlspt = GET_GLOBAL(ATA.devices[driveid].lchs.spt);
-
-    u16 npc   = GET_GLOBAL(ATA.devices[driveid].pchs.cylinders);
-    u16 nph   = GET_GLOBAL(ATA.devices[driveid].pchs.heads);
-    u16 npspt = GET_GLOBAL(ATA.devices[driveid].pchs.spt);
-
-    struct fdpt_s *fdpt = &get_ebda_ptr()->fdpt[driveid];
-    fdpt->precompensation = 0xffff;
-    fdpt->drive_control_byte = 0xc0 | ((nph > 8) << 3);
-    fdpt->landing_zone = npc;
-    fdpt->cylinders = nlc;
-    fdpt->heads = nlh;
-    fdpt->sectors = nlspt;
-
-    if (nlc == npc && nlh == nph && nlspt == npspt)
-        // no logical CHS mapping used, just physical CHS
-        // use Standard Fixed Disk Parameter Table (FDPT)
-        return;
-
-    // complies with Phoenix style Translated Fixed Disk Parameter
-    // Table (FDPT)
-    fdpt->phys_cylinders = npc;
-    fdpt->phys_heads = nph;
-    fdpt->phys_sectors = npspt;
-    fdpt->a0h_signature = 0xa0;
-
-    // Checksum structure.
-    fdpt->checksum -= checksum(fdpt, sizeof(*fdpt));
-
-    if (driveid == 0)
-        SET_IVT(0x41, get_ebda_seg()
-                , offsetof(struct extended_bios_data_area_s, fdpt[0]));
-    else
-        SET_IVT(0x46, get_ebda_seg()
-                , offsetof(struct extended_bios_data_area_s, fdpt[1]));
-}
-
-// Map a drive (that was registered via add_bcv_hd)
-void
-map_drive(int driveid)
-{
-    // fill hdidmap
-    u8 hdcount = GET_BDA(hdcount);
-    dprintf(3, "Mapping driveid %d to %d\n", driveid, hdcount);
-    SET_GLOBAL(ATA.idmap[0][hdcount], driveid);
-    SET_BDA(hdcount, hdcount + 1);
-
-    // Fill "fdpt" structure.
-    fill_fdpt(hdcount);
-}
diff --git a/src/ata.h b/src/ata.h
new file mode 100644 (file)
index 0000000..66477e2
--- /dev/null
+++ b/src/ata.h
@@ -0,0 +1,131 @@
+#ifndef __ATA_H
+#define __ATA_H
+
+#include "types.h" // u8
+#include "config.h" // CONFIG_MAX_ATA_INTERFACES
+
+struct ata_channel_s {
+    u16 iobase1;      // IO Base 1
+    u16 iobase2;      // IO Base 2
+    u16 pci_bdf;
+    u8  irq;          // IRQ
+};
+
+// ata.c
+extern struct ata_channel_s ATA_channels[CONFIG_MAX_ATA_INTERFACES];
+int cdrom_read(struct disk_op_s *op);
+int ata_cmd_packet(int driveid, u8 *cmdbuf, u8 cmdlen
+                   , u32 length, void *buf_fl);
+void ata_setup();
+int process_ata_op(struct disk_op_s *op);
+int process_atapi_op(struct disk_op_s *op);
+
+// Global defines -- ATA register and register bits.
+// command block & control block regs
+#define ATA_CB_DATA  0   // data reg         in/out pio_base_addr1+0
+#define ATA_CB_ERR   1   // error            in     pio_base_addr1+1
+#define ATA_CB_FR    1   // feature reg         out pio_base_addr1+1
+#define ATA_CB_SC    2   // sector count     in/out pio_base_addr1+2
+#define ATA_CB_SN    3   // sector number    in/out pio_base_addr1+3
+#define ATA_CB_CL    4   // cylinder low     in/out pio_base_addr1+4
+#define ATA_CB_CH    5   // cylinder high    in/out pio_base_addr1+5
+#define ATA_CB_DH    6   // device head      in/out pio_base_addr1+6
+#define ATA_CB_STAT  7   // primary status   in     pio_base_addr1+7
+#define ATA_CB_CMD   7   // command             out pio_base_addr1+7
+#define ATA_CB_ASTAT 6   // alternate status in     pio_base_addr2+6
+#define ATA_CB_DC    6   // device control      out pio_base_addr2+6
+#define ATA_CB_DA    7   // device address   in     pio_base_addr2+7
+
+#define ATA_CB_ER_ICRC 0x80    // ATA Ultra DMA bad CRC
+#define ATA_CB_ER_BBK  0x80    // ATA bad block
+#define ATA_CB_ER_UNC  0x40    // ATA uncorrected error
+#define ATA_CB_ER_MC   0x20    // ATA media change
+#define ATA_CB_ER_IDNF 0x10    // ATA id not found
+#define ATA_CB_ER_MCR  0x08    // ATA media change request
+#define ATA_CB_ER_ABRT 0x04    // ATA command aborted
+#define ATA_CB_ER_NTK0 0x02    // ATA track 0 not found
+#define ATA_CB_ER_NDAM 0x01    // ATA address mark not found
+
+#define ATA_CB_ER_P_SNSKEY 0xf0   // ATAPI sense key (mask)
+#define ATA_CB_ER_P_MCR    0x08   // ATAPI Media Change Request
+#define ATA_CB_ER_P_ABRT   0x04   // ATAPI command abort
+#define ATA_CB_ER_P_EOM    0x02   // ATAPI End of Media
+#define ATA_CB_ER_P_ILI    0x01   // ATAPI Illegal Length Indication
+
+// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
+#define ATA_CB_SC_P_TAG    0xf8   // ATAPI tag (mask)
+#define ATA_CB_SC_P_REL    0x04   // ATAPI release
+#define ATA_CB_SC_P_IO     0x02   // ATAPI I/O
+#define ATA_CB_SC_P_CD     0x01   // ATAPI C/D
+
+// bits 7-4 of the device/head (CB_DH) reg
+#define ATA_CB_DH_DEV0 0xa0    // select device 0
+#define ATA_CB_DH_DEV1 0xb0    // select device 1
+#define ATA_CB_DH_LBA 0x40    // use LBA
+
+// status reg (CB_STAT and CB_ASTAT) bits
+#define ATA_CB_STAT_BSY  0x80  // busy
+#define ATA_CB_STAT_RDY  0x40  // ready
+#define ATA_CB_STAT_DF   0x20  // device fault
+#define ATA_CB_STAT_WFT  0x20  // write fault (old name)
+#define ATA_CB_STAT_SKC  0x10  // seek complete
+#define ATA_CB_STAT_SERV 0x10  // service
+#define ATA_CB_STAT_DRQ  0x08  // data request
+#define ATA_CB_STAT_CORR 0x04  // corrected
+#define ATA_CB_STAT_IDX  0x02  // index
+#define ATA_CB_STAT_ERR  0x01  // error (ATA)
+#define ATA_CB_STAT_CHK  0x01  // check (ATAPI)
+
+// device control reg (CB_DC) bits
+#define ATA_CB_DC_HD15   0x08  // bit should always be set to one
+#define ATA_CB_DC_SRST   0x04  // soft reset
+#define ATA_CB_DC_NIEN   0x02  // disable interrupts
+
+// Most mandtory and optional ATA commands (from ATA-3),
+#define ATA_CMD_CFA_ERASE_SECTORS            0xC0
+#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE     0x03
+#define ATA_CMD_CFA_TRANSLATE_SECTOR         0x87
+#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE  0xCD
+#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE   0x38
+#define ATA_CMD_CHECK_POWER_MODE1            0xE5
+#define ATA_CMD_CHECK_POWER_MODE2            0x98
+#define ATA_CMD_DEVICE_RESET                 0x08
+#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC    0x90
+#define ATA_CMD_FLUSH_CACHE                  0xE7
+#define ATA_CMD_FORMAT_TRACK                 0x50
+#define ATA_CMD_IDENTIFY_DEVICE              0xEC
+#define ATA_CMD_IDENTIFY_DEVICE_PACKET       0xA1
+#define ATA_CMD_IDENTIFY_PACKET_DEVICE       0xA1
+#define ATA_CMD_IDLE1                        0xE3
+#define ATA_CMD_IDLE2                        0x97
+#define ATA_CMD_IDLE_IMMEDIATE1              0xE1
+#define ATA_CMD_IDLE_IMMEDIATE2              0x95
+#define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS  0x91
+#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
+#define ATA_CMD_NOP                          0x00
+#define ATA_CMD_PACKET                       0xA0
+#define ATA_CMD_READ_BUFFER                  0xE4
+#define ATA_CMD_READ_DMA                     0xC8
+#define ATA_CMD_READ_DMA_QUEUED              0xC7
+#define ATA_CMD_READ_MULTIPLE                0xC4
+#define ATA_CMD_READ_SECTORS                 0x20
+#define ATA_CMD_READ_VERIFY_SECTORS          0x40
+#define ATA_CMD_RECALIBRATE                  0x10
+#define ATA_CMD_REQUEST_SENSE                0x03
+#define ATA_CMD_SEEK                         0x70
+#define ATA_CMD_SET_FEATURES                 0xEF
+#define ATA_CMD_SET_MULTIPLE_MODE            0xC6
+#define ATA_CMD_SLEEP1                       0xE6
+#define ATA_CMD_SLEEP2                       0x99
+#define ATA_CMD_STANDBY1                     0xE2
+#define ATA_CMD_STANDBY2                     0x96
+#define ATA_CMD_STANDBY_IMMEDIATE1           0xE0
+#define ATA_CMD_STANDBY_IMMEDIATE2           0x94
+#define ATA_CMD_WRITE_BUFFER                 0xE8
+#define ATA_CMD_WRITE_DMA                    0xCA
+#define ATA_CMD_WRITE_DMA_QUEUED             0xCC
+#define ATA_CMD_WRITE_MULTIPLE               0xC5
+#define ATA_CMD_WRITE_SECTORS                0x30
+#define ATA_CMD_WRITE_VERIFY                 0x3C
+
+#endif // ata.h
diff --git a/src/atabits.h b/src/atabits.h
deleted file mode 100644 (file)
index 8495107..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Global defines -- ATA register and register bits.
-// command block & control block regs
-#define ATA_CB_DATA  0   // data reg         in/out pio_base_addr1+0
-#define ATA_CB_ERR   1   // error            in     pio_base_addr1+1
-#define ATA_CB_FR    1   // feature reg         out pio_base_addr1+1
-#define ATA_CB_SC    2   // sector count     in/out pio_base_addr1+2
-#define ATA_CB_SN    3   // sector number    in/out pio_base_addr1+3
-#define ATA_CB_CL    4   // cylinder low     in/out pio_base_addr1+4
-#define ATA_CB_CH    5   // cylinder high    in/out pio_base_addr1+5
-#define ATA_CB_DH    6   // device head      in/out pio_base_addr1+6
-#define ATA_CB_STAT  7   // primary status   in     pio_base_addr1+7
-#define ATA_CB_CMD   7   // command             out pio_base_addr1+7
-#define ATA_CB_ASTAT 6   // alternate status in     pio_base_addr2+6
-#define ATA_CB_DC    6   // device control      out pio_base_addr2+6
-#define ATA_CB_DA    7   // device address   in     pio_base_addr2+7
-
-#define ATA_CB_ER_ICRC 0x80    // ATA Ultra DMA bad CRC
-#define ATA_CB_ER_BBK  0x80    // ATA bad block
-#define ATA_CB_ER_UNC  0x40    // ATA uncorrected error
-#define ATA_CB_ER_MC   0x20    // ATA media change
-#define ATA_CB_ER_IDNF 0x10    // ATA id not found
-#define ATA_CB_ER_MCR  0x08    // ATA media change request
-#define ATA_CB_ER_ABRT 0x04    // ATA command aborted
-#define ATA_CB_ER_NTK0 0x02    // ATA track 0 not found
-#define ATA_CB_ER_NDAM 0x01    // ATA address mark not found
-
-#define ATA_CB_ER_P_SNSKEY 0xf0   // ATAPI sense key (mask)
-#define ATA_CB_ER_P_MCR    0x08   // ATAPI Media Change Request
-#define ATA_CB_ER_P_ABRT   0x04   // ATAPI command abort
-#define ATA_CB_ER_P_EOM    0x02   // ATAPI End of Media
-#define ATA_CB_ER_P_ILI    0x01   // ATAPI Illegal Length Indication
-
-// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
-#define ATA_CB_SC_P_TAG    0xf8   // ATAPI tag (mask)
-#define ATA_CB_SC_P_REL    0x04   // ATAPI release
-#define ATA_CB_SC_P_IO     0x02   // ATAPI I/O
-#define ATA_CB_SC_P_CD     0x01   // ATAPI C/D
-
-// bits 7-4 of the device/head (CB_DH) reg
-#define ATA_CB_DH_DEV0 0xa0    // select device 0
-#define ATA_CB_DH_DEV1 0xb0    // select device 1
-#define ATA_CB_DH_LBA 0x40    // use LBA
-
-// status reg (CB_STAT and CB_ASTAT) bits
-#define ATA_CB_STAT_BSY  0x80  // busy
-#define ATA_CB_STAT_RDY  0x40  // ready
-#define ATA_CB_STAT_DF   0x20  // device fault
-#define ATA_CB_STAT_WFT  0x20  // write fault (old name)
-#define ATA_CB_STAT_SKC  0x10  // seek complete
-#define ATA_CB_STAT_SERV 0x10  // service
-#define ATA_CB_STAT_DRQ  0x08  // data request
-#define ATA_CB_STAT_CORR 0x04  // corrected
-#define ATA_CB_STAT_IDX  0x02  // index
-#define ATA_CB_STAT_ERR  0x01  // error (ATA)
-#define ATA_CB_STAT_CHK  0x01  // check (ATAPI)
-
-// device control reg (CB_DC) bits
-#define ATA_CB_DC_HD15   0x08  // bit should always be set to one
-#define ATA_CB_DC_SRST   0x04  // soft reset
-#define ATA_CB_DC_NIEN   0x02  // disable interrupts
-
-// Most mandtory and optional ATA commands (from ATA-3),
-#define ATA_CMD_CFA_ERASE_SECTORS            0xC0
-#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE     0x03
-#define ATA_CMD_CFA_TRANSLATE_SECTOR         0x87
-#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE  0xCD
-#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE   0x38
-#define ATA_CMD_CHECK_POWER_MODE1            0xE5
-#define ATA_CMD_CHECK_POWER_MODE2            0x98
-#define ATA_CMD_DEVICE_RESET                 0x08
-#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC    0x90
-#define ATA_CMD_FLUSH_CACHE                  0xE7
-#define ATA_CMD_FORMAT_TRACK                 0x50
-#define ATA_CMD_IDENTIFY_DEVICE              0xEC
-#define ATA_CMD_IDENTIFY_DEVICE_PACKET       0xA1
-#define ATA_CMD_IDENTIFY_PACKET_DEVICE       0xA1
-#define ATA_CMD_IDLE1                        0xE3
-#define ATA_CMD_IDLE2                        0x97
-#define ATA_CMD_IDLE_IMMEDIATE1              0xE1
-#define ATA_CMD_IDLE_IMMEDIATE2              0x95
-#define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS  0x91
-#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
-#define ATA_CMD_NOP                          0x00
-#define ATA_CMD_PACKET                       0xA0
-#define ATA_CMD_READ_BUFFER                  0xE4
-#define ATA_CMD_READ_DMA                     0xC8
-#define ATA_CMD_READ_DMA_QUEUED              0xC7
-#define ATA_CMD_READ_MULTIPLE                0xC4
-#define ATA_CMD_READ_SECTORS                 0x20
-#define ATA_CMD_READ_VERIFY_SECTORS          0x40
-#define ATA_CMD_RECALIBRATE                  0x10
-#define ATA_CMD_REQUEST_SENSE                0x03
-#define ATA_CMD_SEEK                         0x70
-#define ATA_CMD_SET_FEATURES                 0xEF
-#define ATA_CMD_SET_MULTIPLE_MODE            0xC6
-#define ATA_CMD_SLEEP1                       0xE6
-#define ATA_CMD_SLEEP2                       0x99
-#define ATA_CMD_STANDBY1                     0xE2
-#define ATA_CMD_STANDBY2                     0x96
-#define ATA_CMD_STANDBY_IMMEDIATE1           0xE0
-#define ATA_CMD_STANDBY_IMMEDIATE2           0x94
-#define ATA_CMD_WRITE_BUFFER                 0xE8
-#define ATA_CMD_WRITE_DMA                    0xCA
-#define ATA_CMD_WRITE_DMA_QUEUED             0xCC
-#define ATA_CMD_WRITE_MULTIPLE               0xC5
-#define ATA_CMD_WRITE_SECTORS                0x30
-#define ATA_CMD_WRITE_VERIFY                 0x3C
index 7eaa07bcbf9c1250eafcff63d6675e5d645d984d..9469c9aa008324114150530198385ce034bfaf4f 100644 (file)
@@ -228,7 +228,7 @@ struct extended_bios_data_area_s {
     struct dpte_s dpte;
 
     // Locks for removable devices
-    u8 cdrom_locks[CONFIG_MAX_ATA_DEVICES];
+    u8 cdrom_locks[CONFIG_MAX_DRIVES];
 
     u16 boot_sequence;
 
diff --git a/src/block.c b/src/block.c
new file mode 100644 (file)
index 0000000..2df2cc4
--- /dev/null
@@ -0,0 +1,211 @@
+// Disk setup and access
+//
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "disk.h" // struct ata_s
+#include "biosvar.h" // GET_GLOBAL
+#include "cmos.h" // inb_cmos
+#include "util.h" // dprintf
+
+struct drives_s Drives VAR16_32;
+
+
+/****************************************************************
+ * Disk geometry translation
+ ****************************************************************/
+
+static u8
+get_translation(int driveid)
+{
+    u8 type = GET_GLOBAL(Drives.drives[driveid].type);
+    if (! CONFIG_COREBOOT && type == DTYPE_ATA) {
+        // Emulators pass in the translation info via nvram.
+        u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
+        u8 channel = ataid / 2;
+        u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
+        translation >>= 2 * (ataid % 4);
+        translation &= 0x03;
+        return translation;
+    }
+
+    // On COREBOOT, use a heuristic to determine translation type.
+    u16 heads = GET_GLOBAL(Drives.drives[driveid].pchs.heads);
+    u16 cylinders = GET_GLOBAL(Drives.drives[driveid].pchs.cylinders);
+    u16 spt = GET_GLOBAL(Drives.drives[driveid].pchs.spt);
+
+    if (cylinders <= 1024 && heads <= 16 && spt <= 63)
+        return TRANSLATION_NONE;
+    if (cylinders * heads <= 131072)
+        return TRANSLATION_LARGE;
+    return TRANSLATION_LBA;
+}
+
+void
+setup_translation(int driveid)
+{
+    u8 translation = get_translation(driveid);
+    SET_GLOBAL(Drives.drives[driveid].translation, translation);
+
+    u8 ataid = GET_GLOBAL(Drives.drives[driveid].cntl_id);
+    u8 channel = ataid / 2;
+    u8 slave = ataid % 2;
+    u16 heads = GET_GLOBAL(Drives.drives[driveid].pchs.heads);
+    u16 cylinders = GET_GLOBAL(Drives.drives[driveid].pchs.cylinders);
+    u16 spt = GET_GLOBAL(Drives.drives[driveid].pchs.spt);
+    u64 sectors = GET_GLOBAL(Drives.drives[driveid].sectors);
+
+    dprintf(1, "ata%d-%d: PCHS=%u/%d/%d translation="
+            , channel, slave, cylinders, heads, spt);
+    switch (translation) {
+    case TRANSLATION_NONE:
+        dprintf(1, "none");
+        break;
+    case TRANSLATION_LBA:
+        dprintf(1, "lba");
+        spt = 63;
+        if (sectors > 63*255*1024) {
+            heads = 255;
+            cylinders = 1024;
+            break;
+        }
+        u32 sect = (u32)sectors / 63;
+        heads = sect / 1024;
+        if (heads>128)
+            heads = 255;
+        else if (heads>64)
+            heads = 128;
+        else if (heads>32)
+            heads = 64;
+        else if (heads>16)
+            heads = 32;
+        else
+            heads = 16;
+        cylinders = sect / heads;
+        break;
+    case TRANSLATION_RECHS:
+        dprintf(1, "r-echs");
+        // Take care not to overflow
+        if (heads==16) {
+            if (cylinders>61439)
+                cylinders=61439;
+            heads=15;
+            cylinders = (u16)((u32)(cylinders)*16/15);
+        }
+        // then go through the large bitshift process
+    case TRANSLATION_LARGE:
+        if (translation == TRANSLATION_LARGE)
+            dprintf(1, "large");
+        while (cylinders > 1024) {
+            cylinders >>= 1;
+            heads <<= 1;
+
+            // If we max out the head count
+            if (heads > 127)
+                break;
+        }
+        break;
+    }
+    // clip to 1024 cylinders in lchs
+    if (cylinders > 1024)
+        cylinders = 1024;
+    dprintf(1, " LCHS=%d/%d/%d\n", cylinders, heads, spt);
+
+    SET_GLOBAL(Drives.drives[driveid].lchs.heads, heads);
+    SET_GLOBAL(Drives.drives[driveid].lchs.cylinders, cylinders);
+    SET_GLOBAL(Drives.drives[driveid].lchs.spt, spt);
+}
+
+
+/****************************************************************
+ * Drive mapping
+ ****************************************************************/
+
+// Fill in Fixed Disk Parameter Table (located in ebda).
+static void
+fill_fdpt(int driveid)
+{
+    if (driveid > 1)
+        return;
+
+    u16 nlc   = GET_GLOBAL(Drives.drives[driveid].lchs.cylinders);
+    u16 nlh   = GET_GLOBAL(Drives.drives[driveid].lchs.heads);
+    u16 nlspt = GET_GLOBAL(Drives.drives[driveid].lchs.spt);
+
+    u16 npc   = GET_GLOBAL(Drives.drives[driveid].pchs.cylinders);
+    u16 nph   = GET_GLOBAL(Drives.drives[driveid].pchs.heads);
+    u16 npspt = GET_GLOBAL(Drives.drives[driveid].pchs.spt);
+
+    struct fdpt_s *fdpt = &get_ebda_ptr()->fdpt[driveid];
+    fdpt->precompensation = 0xffff;
+    fdpt->drive_control_byte = 0xc0 | ((nph > 8) << 3);
+    fdpt->landing_zone = npc;
+    fdpt->cylinders = nlc;
+    fdpt->heads = nlh;
+    fdpt->sectors = nlspt;
+
+    if (nlc == npc && nlh == nph && nlspt == npspt)
+        // no logical CHS mapping used, just physical CHS
+        // use Standard Fixed Disk Parameter Table (FDPT)
+        return;
+
+    // complies with Phoenix style Translated Fixed Disk Parameter
+    // Table (FDPT)
+    fdpt->phys_cylinders = npc;
+    fdpt->phys_heads = nph;
+    fdpt->phys_sectors = npspt;
+    fdpt->a0h_signature = 0xa0;
+
+    // Checksum structure.
+    fdpt->checksum -= checksum(fdpt, sizeof(*fdpt));
+
+    if (driveid == 0)
+        SET_IVT(0x41, get_ebda_seg()
+                , offsetof(struct extended_bios_data_area_s, fdpt[0]));
+    else
+        SET_IVT(0x46, get_ebda_seg()
+                , offsetof(struct extended_bios_data_area_s, fdpt[1]));
+}
+
+// Map a drive (that was registered via add_bcv_hd)
+void
+map_hd_drive(int driveid)
+{
+    // fill hdidmap
+    u8 hdcount = GET_BDA(hdcount);
+    if (hdcount >= ARRAY_SIZE(Drives.idmap[0]))
+        return;
+    dprintf(3, "Mapping hd driveid %d to %d\n", driveid, hdcount);
+    SET_GLOBAL(Drives.idmap[0][hdcount], driveid);
+    SET_BDA(hdcount, hdcount + 1);
+
+    // Fill "fdpt" structure.
+    fill_fdpt(hdcount);
+}
+
+// Map a cd
+void
+map_cd_drive(int driveid)
+{
+    // fill cdidmap
+    u8 cdcount = GET_GLOBAL(Drives.cdcount);
+    if (cdcount >= ARRAY_SIZE(Drives.idmap[1]))
+        return;
+    dprintf(3, "Mapping cd driveid %d to %d\n", driveid, cdcount);
+    SET_GLOBAL(Drives.idmap[1][cdcount], driveid);
+    SET_GLOBAL(Drives.cdcount, cdcount+1);
+}
+
+
+/****************************************************************
+ * Setup
+ ****************************************************************/
+
+void
+drive_setup()
+{
+    memset(&Drives, 0, sizeof(Drives));
+    memset(&Drives.idmap, 0xff, sizeof(Drives.idmap));
+}
index b1dffefe35c5a299e0df7f72fc3e0a38b4862c13..b4067bbfc819da8a11342960b84fe4dd0c7e1ecd 100644 (file)
@@ -168,12 +168,12 @@ static int
 menu_show_cdrom(struct ipl_entry_s *ie, int menupos)
 {
     int i;
-    for (i = 0; i < ATA.cdcount; i++) {
-        int driveid = ATA.idmap[1][i];
+    for (i = 0; i < Drives.cdcount; i++) {
+        int driveid = Drives.idmap[1][i];
         printf("%d. CD-Rom [ata%d-%d %s]\n", menupos + i
-               , driveid / 2, driveid % 2, ATA.devices[driveid].model);
+               , driveid / 2, driveid % 2, Drives.drives[driveid].model);
     }
-    return ATA.cdcount;
+    return Drives.cdcount;
 }
 
 // Show coreboot-fs menu item.
@@ -272,7 +272,7 @@ run_bcv(struct ipl_entry_s *ie)
 {
     switch (ie->type) {
     case IPL_TYPE_HARDDISK:
-        map_drive(ie->vector);
+        map_hd_drive(ie->vector);
         break;
     case IPL_TYPE_BEV:
         call_bcv(ie->vector >> 16, ie->vector & 0xffff);
index c62829a44285fabb21c496d2cae0f8bb614fe18e..ca19da07a4562402d88ef37ba725bc61a6fabcc0 100644 (file)
@@ -1,6 +1,6 @@
 // 16bit code to access cdrom drives.
 //
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 // Copyright (C) 2002  MandrakeSoft S.A.
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
@@ -9,7 +9,7 @@
 #include "util.h" // memset
 #include "bregs.h" // struct bregs
 #include "biosvar.h" // GET_EBDA
-#include "atabits.h" // ATA_CMD_REQUEST_SENSE
+#include "ata.h" // ATA_CMD_REQUEST_SENSE
 
 
 /****************************************************************
@@ -387,7 +387,7 @@ atapi_is_ready(u16 device)
         }
     }
 
-    if (blksize != GET_GLOBAL(ATA.devices[device].blksize)) {
+    if (blksize != GET_GLOBAL(Drives.drives[device].blksize)) {
         printf("Unsupported sector size %u\n", blksize);
         return -1;
     }
@@ -401,9 +401,9 @@ int
 cdrom_boot(int cdid)
 {
     // Verify device is a cdrom.
-    if (cdid >= ATA.cdcount)
+    if (cdid >= Drives.cdcount)
         return 1;
-    int driveid = GET_GLOBAL(ATA.idmap[1][cdid]);
+    int driveid = GET_GLOBAL(Drives.idmap[1][cdid]);
 
     int ret = atapi_is_ready(driveid);
     if (ret)
index 98b69e82d11b187b6e30ac56e50267bebe522536..a81e1eccc84626c9c94033d09685ab860f1f0006 100644 (file)
@@ -24,7 +24,9 @@
 // Screen writes are also sent to debug ports.
 #define CONFIG_SCREEN_AND_DEBUG 1
 
-// Support for int13 floppy drive access
+// Support int13 disk/floppy drive functions
+#define CONFIG_DRIVES 1
+// Support floppy drive access
 #define CONFIG_FLOPPY_SUPPORT 1
 // Support for IDE disk code
 #define CONFIG_ATA 1
 // Space to reserve in high-memory for tables
 #define CONFIG_MAX_HIGHTABLE (64*1024)
 
+// Maximum number of ATA controllers to support
 #define CONFIG_MAX_ATA_INTERFACES 4
-#define CONFIG_MAX_ATA_DEVICES  (CONFIG_MAX_ATA_INTERFACES*2)
+// Maximum number of internal drives supported
+#define CONFIG_MAX_DRIVES 8
+// Largest supported externaly facing drive id
+#define CONFIG_MAX_EXTDRIVE 16
 
 #define CONFIG_MODEL_ID      0xFC
 #define CONFIG_SUBMODEL_ID   0x00
index 609beaad0378e2261fc54f1335c0d00ec05278af..263c0d9a802e2e18df621da9a3978d50e58660a2 100644 (file)
@@ -12,7 +12,7 @@
 #include "pic.h" // eoi_pic2
 #include "bregs.h" // struct bregs
 #include "pci.h" // pci_bdf_to_bus
-#include "atabits.h" // ATA_CB_DC
+#include "ata.h" // ATA_CB_DC
 
 
 /****************************************************************
@@ -56,7 +56,7 @@ __send_disk_op(struct disk_op_s *op_far, u16 op_seg)
     irq_enable();
 
     int status = 0;
-    u8 type = GET_GLOBAL(ATA.devices[dop.driveid].type);
+    u8 type = GET_GLOBAL(Drives.drives[dop.driveid].type);
     if (type == DTYPE_ATA)
         status = process_ata_op(&dop);
     else if (type == DTYPE_ATAPI)
@@ -77,7 +77,7 @@ __send_disk_op(struct disk_op_s *op_far, u16 op_seg)
 static int
 send_disk_op(struct disk_op_s *op)
 {
-    if (! CONFIG_ATA)
+    if (! CONFIG_DRIVES)
         return -1;
 
     return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op);
@@ -124,7 +124,7 @@ basic_access(struct bregs *regs, u8 device, u16 command)
     struct disk_op_s dop;
     dop.driveid = device;
     dop.command = command;
-    int lba = legacy_lba(regs, get_global_seg(), &ATA.devices[device].lchs);
+    int lba = legacy_lba(regs, get_global_seg(), &Drives.drives[device].lchs);
     if (lba < 0)
         return;
     dop.lba = lba;
@@ -218,7 +218,7 @@ extended_access(struct bregs *regs, u8 device, u16 command)
     dop.lba = GET_INT13EXT(regs, lba);
     dop.command = command;
     dop.driveid = device;
-    if (dop.lba >= GET_GLOBAL(ATA.devices[device].sectors)) {
+    if (dop.lba >= GET_GLOBAL(Drives.drives[device].sectors)) {
         dprintf(1, "int13_harddisk: function %02x. LBA out of range\n"
                 , regs->ah);
         disk_ret(regs, DISK_RET_EPARAM);
@@ -300,9 +300,9 @@ static void
 disk_1308(struct bregs *regs, u8 device)
 {
     // Get logical geometry from table
-    u16 nlc = GET_GLOBAL(ATA.devices[device].lchs.cylinders);
-    u16 nlh = GET_GLOBAL(ATA.devices[device].lchs.heads);
-    u16 nlspt = GET_GLOBAL(ATA.devices[device].lchs.spt);
+    u16 nlc = GET_GLOBAL(Drives.drives[device].lchs.cylinders);
+    u16 nlh = GET_GLOBAL(Drives.drives[device].lchs.heads);
+    u16 nlspt = GET_GLOBAL(Drives.drives[device].lchs.spt);
     u16 count = GET_BDA(hdcount);
 
     nlc = nlc - 2; /* 0 based , last sector not used */
@@ -372,9 +372,9 @@ static void
 disk_1315(struct bregs *regs, u8 device)
 {
     // Get logical geometry from table
-    u16 nlc   = GET_GLOBAL(ATA.devices[device].lchs.cylinders);
-    u16 nlh   = GET_GLOBAL(ATA.devices[device].lchs.heads);
-    u16 nlspt = GET_GLOBAL(ATA.devices[device].lchs.spt);
+    u16 nlc   = GET_GLOBAL(Drives.drives[device].lchs.cylinders);
+    u16 nlh   = GET_GLOBAL(Drives.drives[device].lchs.heads);
+    u16 nlspt = GET_GLOBAL(Drives.drives[device].lchs.spt);
 
     // Compute sector count seen by int13
     u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nlspt;
@@ -453,12 +453,12 @@ disk_1348(struct bregs *regs, u8 device)
 
     // EDD 1.x
 
-    u8  type    = GET_GLOBAL(ATA.devices[device].type);
-    u16 npc     = GET_GLOBAL(ATA.devices[device].pchs.cylinders);
-    u16 nph     = GET_GLOBAL(ATA.devices[device].pchs.heads);
-    u16 npspt   = GET_GLOBAL(ATA.devices[device].pchs.spt);
-    u64 lba     = GET_GLOBAL(ATA.devices[device].sectors);
-    u16 blksize = GET_GLOBAL(ATA.devices[device].blksize);
+    u8  type    = GET_GLOBAL(Drives.drives[device].type);
+    u16 npc     = GET_GLOBAL(Drives.drives[device].pchs.cylinders);
+    u16 nph     = GET_GLOBAL(Drives.drives[device].pchs.heads);
+    u16 npspt   = GET_GLOBAL(Drives.drives[device].pchs.spt);
+    u64 lba     = GET_GLOBAL(Drives.drives[device].sectors);
+    u16 blksize = GET_GLOBAL(Drives.drives[device].blksize);
 
     dprintf(DEBUG_HDL_13, "disk_1348 size=%d t=%d chs=%d,%d,%d lba=%d bs=%d\n"
             , size, type, npc, nph, npspt, (u32)lba, blksize);
@@ -500,16 +500,16 @@ disk_1348(struct bregs *regs, u8 device)
                  , offsetof(struct extended_bios_data_area_s, dpte));
 
     // Fill in dpte
-    u8 ataid = GET_GLOBAL(ATA.devices[device].cntl_id);
+    u8 ataid = GET_GLOBAL(Drives.drives[device].cntl_id);
     u8 channel = ataid / 2;
     u8 slave = ataid % 2;
-    u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
-    u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
-    u8 irq = GET_GLOBAL(ATA.channels[channel].irq);
+    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
+    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
+    u8 irq = GET_GLOBAL(ATA_channels[channel].irq);
 
     u16 options = 0;
     if (type == DTYPE_ATA) {
-        u8 translation = GET_GLOBAL(ATA.devices[device].translation);
+        u8 translation = GET_GLOBAL(Drives.drives[device].translation);
         if (translation != TRANSLATION_NONE) {
             options |= 1<<3; // CHS translation
             if (translation == TRANSLATION_LBA)
@@ -559,7 +559,7 @@ disk_1348(struct bregs *regs, u8 device)
     SET_INT13DPT(regs, host_bus[2], 'I');
     SET_INT13DPT(regs, host_bus[3], 0);
 
-    u32 bdf = GET_GLOBAL(ATA.channels[channel].pci_bdf);
+    u32 bdf = GET_GLOBAL(ATA_channels[channel].pci_bdf);
     u32 path = (pci_bdf_to_bus(bdf) | (pci_bdf_to_dev(bdf) << 8)
                 | (pci_bdf_to_fn(bdf) << 16));
     SET_INT13DPT(regs, iface_path, path);
@@ -680,25 +680,25 @@ disk_13(struct bregs *regs, u8 device)
  * Entry points
  ****************************************************************/
 
-static u8
+static int
 get_device(struct bregs *regs, u8 iscd, u8 drive)
 {
     // basic check : device has to be defined
-    if (drive >= CONFIG_MAX_ATA_DEVICES) {
+    if (drive >= ARRAY_SIZE(Drives.idmap[0])) {
         disk_ret(regs, DISK_RET_EPARAM);
-        return CONFIG_MAX_ATA_DEVICES;
+        return -1;
     }
 
     // Get the ata channel
-    u8 device = GET_GLOBAL(ATA.idmap[iscd][drive]);
+    u8 driveid = GET_GLOBAL(Drives.idmap[iscd][drive]);
 
     // basic check : device has to be valid
-    if (device >= CONFIG_MAX_ATA_DEVICES) {
+    if (driveid >= ARRAY_SIZE(Drives.drives)) {
         disk_ret(regs, DISK_RET_EPARAM);
-        return CONFIG_MAX_ATA_DEVICES;
+        return -1;
     }
 
-    return device;
+    return driveid;
 }
 
 static void
@@ -709,24 +709,24 @@ handle_legacy_disk(struct bregs *regs, u8 drive)
         return;
     }
 
-    if (! CONFIG_ATA) {
+    if (! CONFIG_DRIVES) {
         // XXX - old code had other disk access method.
         disk_ret(regs, DISK_RET_EPARAM);
         return;
     }
 
     if (drive >= 0xe0) {
-        u8 device = get_device(regs, 1, drive - 0xe0);
-        if (device >= CONFIG_MAX_ATA_DEVICES)
+        int driveid = get_device(regs, 1, drive - 0xe0);
+        if (driveid < 0)
             return;
-        cdrom_13(regs, device);
+        cdrom_13(regs, driveid);
         return;
     }
 
-    u8 device = get_device(regs, 0, drive - 0x80);
-    if (device >= CONFIG_MAX_ATA_DEVICES)
+    int driveid = get_device(regs, 0, drive - 0x80);
+    if (driveid < 0)
         return;
-    disk_13(regs, device);
+    disk_13(regs, driveid);
 }
 
 void VISIBLE16
index 9441fe13b2d37f5364d529b7e2ea3e003274b98c..384ea2dc9cf516741fcff319c76dd7a1793a7394 100644 (file)
@@ -167,15 +167,8 @@ struct chs_s {
     u16 spt;        // # sectors / track
 };
 
-struct ata_channel_s {
-    u16 iobase1;      // IO Base 1
-    u16 iobase2;      // IO Base 2
-    u16 pci_bdf;
-    u8  irq;          // IRQ
-};
-
-struct ata_device_s {
-    u8  type;         // Detected type of ata (ata/atapi/none)
+struct drive_s {
+    u8  type;         // Detected type of drive (ata/atapi/none)
     u8  removable;    // Removable device flag
     u16 blksize;      // block size
     int cntl_id;
@@ -198,16 +191,13 @@ struct ata_device_s {
 #define TRANSLATION_LARGE 2
 #define TRANSLATION_RECHS 3
 
-struct ata_s {
-    // ATA channels info
-    struct ata_channel_s channels[CONFIG_MAX_ATA_INTERFACES];
-
-    // ATA devices info
-    struct ata_device_s devices[CONFIG_MAX_ATA_DEVICES];
+struct drives_s {
+    // info on each internally handled drive
+    struct drive_s drives[CONFIG_MAX_DRIVES];
     //
-    // map between bios hd/cd id and ata channels
+    // map between bios hd/cd id and driveid index into drives[]
     u8 cdcount;
-    u8 idmap[2][CONFIG_MAX_ATA_DEVICES];
+    u8 idmap[2][CONFIG_MAX_EXTDRIVE];
 };
 
 
@@ -215,20 +205,17 @@ struct ata_s {
  * Function defs
  ****************************************************************/
 
-// ata.c
-extern struct ata_s ATA;
-int cdrom_read(struct disk_op_s *op);
-int ata_cmd_packet(int driveid, u8 *cmdbuf, u8 cmdlen
-                   , u32 length, void *buf_fl);
-void hard_drive_setup();
-int process_ata_op(struct disk_op_s *op);
-int process_atapi_op(struct disk_op_s *op);
-void map_drive(int driveid);
+// block.c
+extern struct drives_s Drives;
+void setup_translation(int driveid);
+void map_hd_drive(int driveid);
+void map_cd_drive(int driveid);
+void drive_setup();
 
 // floppy.c
 extern u8 FloppyCount;
 extern struct floppy_ext_dbt_s diskette_param_table2;
-void floppy_drive_setup();
+void floppy_setup();
 void floppy_13(struct bregs *regs, u8 drive);
 void floppy_tick();
 
index 12bed1e1fbcb34e18a1fbc75ec3c5839841d91aa..7f236ce47953e0c8bed9c26dbd1064f3606dbe2c 100644 (file)
@@ -1,6 +1,6 @@
 // 16bit code to access floppy drives.
 //
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 // Copyright (C) 2002  MandrakeSoft S.A.
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
@@ -60,7 +60,7 @@ u8 FloppyCount VAR16_32;
 u8 FloppyTypes[2] VAR16_32;
 
 void
-floppy_drive_setup()
+floppy_setup()
 {
     if (! CONFIG_FLOPPY_SUPPORT)
         return;
index 32d22c88e89df459beea28a1b1504aa1a987a0c9..9bb51326c814009ae050b83fcac1e0f566d5eee4 100644 (file)
@@ -11,6 +11,7 @@
 #include "util.h" // memset
 #include "biosvar.h" // struct bios_data_area_s
 #include "disk.h" // floppy_drive_setup
+#include "ata.h" // ata_setup
 #include "memmap.h" // add_e820
 #include "pic.h" // pic_setup
 #include "pci.h" // create_pirtable
@@ -185,8 +186,9 @@ post()
 
     boot_setup();
 
-    floppy_drive_setup();
-    hard_drive_setup();
+    drive_setup();
+    floppy_setup();
+    ata_setup();
 
     optionrom_setup();