X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fblock.c;h=eeebd83b82091881d6ab65d59f90b4f5167c9886;hb=refs%2Fheads%2Fcoreboot;hp=63aa368d1e8b2f91b8ed59e11c2f99ec0e34e9a8;hpb=d7e998fdd0ea1cacbc83e9add182c49917bf35e6;p=seabios.git diff --git a/src/block.c b/src/block.c index 63aa368..eeebd83 100644 --- a/src/block.c +++ b/src/block.c @@ -10,17 +10,48 @@ #include "cmos.h" // inb_cmos #include "util.h" // dprintf #include "ata.h" // process_ata_op +#include "ahci.h" // process_ahci_op +#include "virtio-blk.h" // process_virtio_blk_op +#include "blockcmd.h" // cdb_* -struct drives_s Drives VAR16VISIBLE; +u8 FloppyCount VAR16VISIBLE; +u8 CDCount; +struct drive_s *IDMap[3][CONFIG_MAX_EXTDRIVE] VAR16VISIBLE; +u8 *bounce_buf_fl VAR16VISIBLE; struct drive_s * getDrive(u8 exttype, u8 extdriveoffset) { - if (extdriveoffset >= ARRAY_SIZE(Drives.idmap[0])) + if (extdriveoffset >= ARRAY_SIZE(IDMap[0])) return NULL; - return RETRIEVE_GLOBAL_PTR(GET_GLOBAL(Drives.idmap[exttype][extdriveoffset])); + struct drive_s *drive_gf = GET_GLOBAL(IDMap[exttype][extdriveoffset]); + if (!drive_gf) + return NULL; + return GLOBALFLAT2GLOBAL(drive_gf); } +int getDriveId(u8 exttype, struct drive_s *drive_g) +{ + int i; + for (i = 0; i < ARRAY_SIZE(IDMap[0]); i++) + if (getDrive(exttype, i) == drive_g) + return i; + return -1; +} + +int bounce_buf_init(void) +{ + if (bounce_buf_fl) + return 0; + + u8 *buf = malloc_low(CDROM_SECTOR_SIZE); + if (!buf) { + warn_noalloc(); + return -1; + } + bounce_buf_fl = buf; + return 0; +} /**************************************************************** * Disk geometry translation @@ -40,10 +71,15 @@ get_translation(struct drive_s *drive_g) return translation; } - // On COREBOOT, use a heuristic to determine translation type. + // Otherwise use a heuristic to determine translation type. u16 heads = GET_GLOBAL(drive_g->pchs.heads); u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders); u16 spt = GET_GLOBAL(drive_g->pchs.spt); + u64 sectors = GET_GLOBAL(drive_g->sectors); + u64 psectors = (u64)heads * cylinders * spt; + if (!heads || !cylinders || !spt || psectors > sectors) + // pchs doesn't look valid - use LBA. + return TRANSLATION_LBA; if (cylinders <= 1024 && heads <= 16 && spt <= 63) return TRANSLATION_NONE; @@ -52,15 +88,12 @@ get_translation(struct drive_s *drive_g) return TRANSLATION_LBA; } -void +static void setup_translation(struct drive_s *drive_g) { u8 translation = get_translation(drive_g); SET_GLOBAL(drive_g->translation, translation); - u8 ataid = GET_GLOBAL(drive_g->cntl_id); - u8 channel = ataid / 2; - u8 slave = ataid % 2; u16 heads = GET_GLOBAL(drive_g->pchs.heads); u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders); u16 spt = GET_GLOBAL(drive_g->pchs.spt); @@ -120,11 +153,12 @@ setup_translation(struct drive_s *drive_g) // clip to 1024 cylinders in lchs if (cylinders > 1024) cylinders = 1024; - dprintf(1, "ata%d-%d: PCHS=%u/%d/%d translation=%s LCHS=%d/%d/%d\n" - , channel, slave + dprintf(1, "drive %p: PCHS=%u/%d/%d translation=%s LCHS=%d/%d/%d s=%d\n" + , drive_g , drive_g->pchs.cylinders, drive_g->pchs.heads, drive_g->pchs.spt , desc - , cylinders, heads, spt); + , cylinders, heads, spt + , (u32)sectors); SET_GLOBAL(drive_g->lchs.heads, heads); SET_GLOBAL(drive_g->lchs.cylinders, cylinders); @@ -181,52 +215,33 @@ fill_fdpt(struct drive_s *drive_g, int hdid) struct extended_bios_data_area_s, fdpt[1]))); } -// Map a drive (that was registered via add_bcv_hd) -void -map_hd_drive(struct drive_s *drive_g) -{ - // fill hdidmap - u8 hdcount = GET_BDA(hdcount); - if (hdcount >= ARRAY_SIZE(Drives.idmap[0])) { - warn_noalloc(); - return; - } - dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdcount); - Drives.idmap[EXTTYPE_HD][hdcount] = STORE_GLOBAL_PTR(drive_g); - SET_BDA(hdcount, hdcount + 1); - - // Fill "fdpt" structure. - fill_fdpt(drive_g, hdcount); -} - // Find spot to add a drive static void -add_ordered_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive_g) +add_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive_g) { - if (*count >= ARRAY_SIZE(Drives.idmap[0])) { + if (*count >= ARRAY_SIZE(IDMap[0])) { warn_noalloc(); return; } - struct drive_s **pos = &idmap[*count]; + idmap[*count] = drive_g; *count = *count + 1; - if (CONFIG_THREADS) { - // Add to idmap with assured drive order. - struct drive_s **end = pos; - for (;;) { - struct drive_s **prev = pos - 1; - if (prev < idmap) - break; - struct drive_s *prevdrive = *prev; - if (prevdrive->type < drive_g->type - || (prevdrive->type == drive_g->type - && prevdrive->cntl_id < drive_g->cntl_id)) - break; - pos--; - } - if (pos != end) - memmove(pos+1, pos, (void*)end-(void*)pos); - } - *pos = STORE_GLOBAL_PTR(drive_g); +} + +// Map a hard drive +void +map_hd_drive(struct drive_s *drive_g) +{ + ASSERT32FLAT(); + struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0); + int hdid = bda->hdcount; + dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdid); + add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive_g); + + // Setup disk geometry translation. + setup_translation(drive_g); + + // Fill "fdpt" structure. + fill_fdpt(drive_g, hdid); } // Map a cd @@ -234,60 +249,55 @@ void map_cd_drive(struct drive_s *drive_g) { dprintf(3, "Mapping cd drive %p\n", drive_g); - add_ordered_drive(Drives.idmap[EXTTYPE_CD], &Drives.cdcount, drive_g); + add_drive(IDMap[EXTTYPE_CD], &CDCount, drive_g); } // Map a floppy void map_floppy_drive(struct drive_s *drive_g) { - // fill idmap dprintf(3, "Mapping floppy drive %p\n", drive_g); - add_ordered_drive(Drives.idmap[EXTTYPE_FLOPPY], &Drives.floppycount - , drive_g); + add_drive(IDMap[EXTTYPE_FLOPPY], &FloppyCount, drive_g); // Update equipment word bits for floppy - if (Drives.floppycount == 1) { + if (FloppyCount == 1) { // 1 drive, ready for boot SETBITS_BDA(equipment_list_flags, 0x01); SET_BDA(floppy_harddisk_info, 0x07); - } else if (Drives.floppycount >= 2) { + } else if (FloppyCount >= 2) { // 2 drives, ready for boot SETBITS_BDA(equipment_list_flags, 0x41); SET_BDA(floppy_harddisk_info, 0x77); } } -// Show a one line description (without trailing newline) of a drive. -void -describe_drive(struct drive_s *drive_g) -{ - ASSERT32FLAT(); - u8 type = GET_GLOBAL(drive_g->type); - switch (type) { - case DTYPE_FLOPPY: - describe_floppy(drive_g); - break; - case DTYPE_ATA: - describe_ata(drive_g); - break; - case DTYPE_ATAPI: - describe_atapi(drive_g); - break; - case DTYPE_RAMDISK: - describe_ramdisk(drive_g); - break; - default: - printf("Unknown"); - break; - } -} - /**************************************************************** * 16bit calling interface ****************************************************************/ +int +process_scsi_op(struct disk_op_s *op) +{ + if (!CONFIG_USB_MSC) + return 0; + switch (op->command) { + case CMD_READ: + return cdb_read(op); + case CMD_WRITE: + return cdb_write(op); + case CMD_FORMAT: + case CMD_RESET: + case CMD_ISREADY: + case CMD_VERIFY: + case CMD_SEEK: + return DISK_RET_SUCCESS; + default: + op->count = 0; + return DISK_RET_EPARAM; + } +} + // Execute a disk_op request. int process_op(struct disk_op_s *op) @@ -305,6 +315,12 @@ process_op(struct disk_op_s *op) return process_ramdisk_op(op); case DTYPE_CDEMU: return process_cdemu_op(op); + case DTYPE_VIRTIO_BLK: + return process_virtio_blk_op(op); + case DTYPE_AHCI: + return process_ahci_op(op); + case DTYPE_USB: + return process_scsi_op(op); default: op->count = 0; return DISK_RET_EPARAM; @@ -340,16 +356,5 @@ send_disk_op(struct disk_op_s *op) if (! CONFIG_DRIVES) return -1; - return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op); -} - - -/**************************************************************** - * Setup - ****************************************************************/ - -void -drive_setup(void) -{ - memset(&Drives, 0, sizeof(Drives)); + return stack_hop((u32)op, GET_SEG(SS), __send_disk_op); }