Annotation of qemu/roms/seabios/src/block.c, revision 1.1.1.6

1.1       root        1: // Disk setup and access
                      2: //
                      3: // Copyright (C) 2008,2009  Kevin O'Connor <[email protected]>
                      4: // Copyright (C) 2002  MandrakeSoft S.A.
                      5: //
                      6: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      7: 
                      8: #include "disk.h" // struct ata_s
                      9: #include "biosvar.h" // GET_GLOBAL
                     10: #include "cmos.h" // inb_cmos
                     11: #include "util.h" // dprintf
                     12: #include "ata.h" // process_ata_op
1.1.1.4   root       13: #include "ahci.h" // process_ahci_op
1.1.1.6 ! root       14: #include "virtio-blk.h" // process_virtio_blk_op
        !            15: #include "blockcmd.h" // cdb_*
1.1       root       16: 
1.1.1.4   root       17: u8 FloppyCount VAR16VISIBLE;
                     18: u8 CDCount;
                     19: struct drive_s *IDMap[3][CONFIG_MAX_EXTDRIVE] VAR16VISIBLE;
1.1.1.5   root       20: u8 *bounce_buf_fl VAR16VISIBLE;
1.1       root       21: 
                     22: struct drive_s *
                     23: getDrive(u8 exttype, u8 extdriveoffset)
                     24: {
1.1.1.4   root       25:     if (extdriveoffset >= ARRAY_SIZE(IDMap[0]))
1.1       root       26:         return NULL;
1.1.1.4   root       27:     struct drive_s *drive_gf = GET_GLOBAL(IDMap[exttype][extdriveoffset]);
1.1.1.3   root       28:     if (!drive_gf)
1.1       root       29:         return NULL;
1.1.1.3   root       30:     return GLOBALFLAT2GLOBAL(drive_gf);
1.1       root       31: }
                     32: 
1.1.1.4   root       33: int getDriveId(u8 exttype, struct drive_s *drive_g)
                     34: {
                     35:     int i;
                     36:     for (i = 0; i < ARRAY_SIZE(IDMap[0]); i++)
                     37:         if (getDrive(exttype, i) == drive_g)
                     38:             return i;
                     39:     return -1;
                     40: }
                     41: 
1.1.1.5   root       42: int bounce_buf_init(void)
                     43: {
                     44:     if (bounce_buf_fl)
                     45:         return 0;
                     46: 
                     47:     u8 *buf = malloc_low(CDROM_SECTOR_SIZE);
                     48:     if (!buf) {
                     49:         warn_noalloc();
                     50:         return -1;
                     51:     }
                     52:     bounce_buf_fl = buf;
                     53:     return 0;
                     54: }
1.1       root       55: 
                     56: /****************************************************************
                     57:  * Disk geometry translation
                     58:  ****************************************************************/
                     59: 
                     60: static u8
                     61: get_translation(struct drive_s *drive_g)
                     62: {
                     63:     u8 type = GET_GLOBAL(drive_g->type);
                     64:     if (! CONFIG_COREBOOT && type == DTYPE_ATA) {
                     65:         // Emulators pass in the translation info via nvram.
                     66:         u8 ataid = GET_GLOBAL(drive_g->cntl_id);
                     67:         u8 channel = ataid / 2;
                     68:         u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
                     69:         translation >>= 2 * (ataid % 4);
                     70:         translation &= 0x03;
                     71:         return translation;
                     72:     }
                     73: 
1.1.1.3   root       74:     // Otherwise use a heuristic to determine translation type.
1.1       root       75:     u16 heads = GET_GLOBAL(drive_g->pchs.heads);
                     76:     u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders);
                     77:     u16 spt = GET_GLOBAL(drive_g->pchs.spt);
1.1.1.3   root       78:     u64 sectors = GET_GLOBAL(drive_g->sectors);
                     79:     u64 psectors = (u64)heads * cylinders * spt;
                     80:     if (!heads || !cylinders || !spt || psectors > sectors)
                     81:         // pchs doesn't look valid - use LBA.
                     82:         return TRANSLATION_LBA;
1.1       root       83: 
                     84:     if (cylinders <= 1024 && heads <= 16 && spt <= 63)
                     85:         return TRANSLATION_NONE;
                     86:     if (cylinders * heads <= 131072)
                     87:         return TRANSLATION_LARGE;
                     88:     return TRANSLATION_LBA;
                     89: }
                     90: 
1.1.1.4   root       91: static void
1.1       root       92: setup_translation(struct drive_s *drive_g)
                     93: {
                     94:     u8 translation = get_translation(drive_g);
                     95:     SET_GLOBAL(drive_g->translation, translation);
                     96: 
                     97:     u16 heads = GET_GLOBAL(drive_g->pchs.heads);
                     98:     u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders);
                     99:     u16 spt = GET_GLOBAL(drive_g->pchs.spt);
                    100:     u64 sectors = GET_GLOBAL(drive_g->sectors);
                    101:     const char *desc = NULL;
                    102: 
                    103:     switch (translation) {
                    104:     default:
                    105:     case TRANSLATION_NONE:
                    106:         desc = "none";
                    107:         break;
                    108:     case TRANSLATION_LBA:
                    109:         desc = "lba";
                    110:         spt = 63;
                    111:         if (sectors > 63*255*1024) {
                    112:             heads = 255;
                    113:             cylinders = 1024;
                    114:             break;
                    115:         }
                    116:         u32 sect = (u32)sectors / 63;
                    117:         heads = sect / 1024;
                    118:         if (heads>128)
                    119:             heads = 255;
                    120:         else if (heads>64)
                    121:             heads = 128;
                    122:         else if (heads>32)
                    123:             heads = 64;
                    124:         else if (heads>16)
                    125:             heads = 32;
                    126:         else
                    127:             heads = 16;
                    128:         cylinders = sect / heads;
                    129:         break;
                    130:     case TRANSLATION_RECHS:
                    131:         desc = "r-echs";
                    132:         // Take care not to overflow
                    133:         if (heads==16) {
                    134:             if (cylinders>61439)
                    135:                 cylinders=61439;
                    136:             heads=15;
                    137:             cylinders = (u16)((u32)(cylinders)*16/15);
                    138:         }
                    139:         // then go through the large bitshift process
                    140:     case TRANSLATION_LARGE:
                    141:         if (translation == TRANSLATION_LARGE)
                    142:             desc = "large";
                    143:         while (cylinders > 1024) {
                    144:             cylinders >>= 1;
                    145:             heads <<= 1;
                    146: 
                    147:             // If we max out the head count
                    148:             if (heads > 127)
                    149:                 break;
                    150:         }
                    151:         break;
                    152:     }
                    153:     // clip to 1024 cylinders in lchs
                    154:     if (cylinders > 1024)
                    155:         cylinders = 1024;
1.1.1.3   root      156:     dprintf(1, "drive %p: PCHS=%u/%d/%d translation=%s LCHS=%d/%d/%d s=%d\n"
                    157:             , drive_g
1.1       root      158:             , drive_g->pchs.cylinders, drive_g->pchs.heads, drive_g->pchs.spt
                    159:             , desc
1.1.1.3   root      160:             , cylinders, heads, spt
                    161:             , (u32)sectors);
1.1       root      162: 
                    163:     SET_GLOBAL(drive_g->lchs.heads, heads);
                    164:     SET_GLOBAL(drive_g->lchs.cylinders, cylinders);
                    165:     SET_GLOBAL(drive_g->lchs.spt, spt);
                    166: }
                    167: 
                    168: 
                    169: /****************************************************************
                    170:  * Drive mapping
                    171:  ****************************************************************/
                    172: 
                    173: // Fill in Fixed Disk Parameter Table (located in ebda).
                    174: static void
                    175: fill_fdpt(struct drive_s *drive_g, int hdid)
                    176: {
                    177:     if (hdid > 1)
                    178:         return;
                    179: 
                    180:     u16 nlc   = GET_GLOBAL(drive_g->lchs.cylinders);
                    181:     u16 nlh   = GET_GLOBAL(drive_g->lchs.heads);
                    182:     u16 nlspt = GET_GLOBAL(drive_g->lchs.spt);
                    183: 
                    184:     u16 npc   = GET_GLOBAL(drive_g->pchs.cylinders);
                    185:     u16 nph   = GET_GLOBAL(drive_g->pchs.heads);
                    186:     u16 npspt = GET_GLOBAL(drive_g->pchs.spt);
                    187: 
                    188:     struct fdpt_s *fdpt = &get_ebda_ptr()->fdpt[hdid];
                    189:     fdpt->precompensation = 0xffff;
                    190:     fdpt->drive_control_byte = 0xc0 | ((nph > 8) << 3);
                    191:     fdpt->landing_zone = npc;
                    192:     fdpt->cylinders = nlc;
                    193:     fdpt->heads = nlh;
                    194:     fdpt->sectors = nlspt;
                    195: 
1.1.1.2   root      196:     if (nlc != npc || nlh != nph || nlspt != npspt) {
                    197:         // Logical mapping present - use extended structure.
1.1       root      198: 
1.1.1.2   root      199:         // complies with Phoenix style Translated Fixed Disk Parameter
                    200:         // Table (FDPT)
                    201:         fdpt->phys_cylinders = npc;
                    202:         fdpt->phys_heads = nph;
                    203:         fdpt->phys_sectors = npspt;
                    204:         fdpt->a0h_signature = 0xa0;
1.1       root      205: 
1.1.1.2   root      206:         // Checksum structure.
                    207:         fdpt->checksum -= checksum(fdpt, sizeof(*fdpt));
                    208:     }
1.1       root      209: 
                    210:     if (hdid == 0)
                    211:         SET_IVT(0x41, SEGOFF(get_ebda_seg(), offsetof(
                    212:                                  struct extended_bios_data_area_s, fdpt[0])));
                    213:     else
                    214:         SET_IVT(0x46, SEGOFF(get_ebda_seg(), offsetof(
                    215:                                  struct extended_bios_data_area_s, fdpt[1])));
                    216: }
                    217: 
                    218: // Find spot to add a drive
                    219: static void
1.1.1.4   root      220: add_drive(struct drive_s **idmap, u8 *count, struct drive_s *drive_g)
1.1       root      221: {
1.1.1.4   root      222:     if (*count >= ARRAY_SIZE(IDMap[0])) {
1.1.1.3   root      223:         warn_noalloc();
1.1       root      224:         return;
                    225:     }
1.1.1.4   root      226:     idmap[*count] = drive_g;
1.1       root      227:     *count = *count + 1;
1.1.1.4   root      228: }
                    229: 
                    230: // Map a hard drive
                    231: void
                    232: map_hd_drive(struct drive_s *drive_g)
                    233: {
                    234:     ASSERT32FLAT();
                    235:     struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
                    236:     int hdid = bda->hdcount;
                    237:     dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdid);
                    238:     add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive_g);
                    239: 
                    240:     // Setup disk geometry translation.
                    241:     setup_translation(drive_g);
                    242: 
                    243:     // Fill "fdpt" structure.
                    244:     fill_fdpt(drive_g, hdid);
1.1       root      245: }
                    246: 
                    247: // Map a cd
                    248: void
                    249: map_cd_drive(struct drive_s *drive_g)
                    250: {
                    251:     dprintf(3, "Mapping cd drive %p\n", drive_g);
1.1.1.4   root      252:     add_drive(IDMap[EXTTYPE_CD], &CDCount, drive_g);
1.1       root      253: }
                    254: 
                    255: // Map a floppy
                    256: void
                    257: map_floppy_drive(struct drive_s *drive_g)
                    258: {
                    259:     dprintf(3, "Mapping floppy drive %p\n", drive_g);
1.1.1.4   root      260:     add_drive(IDMap[EXTTYPE_FLOPPY], &FloppyCount, drive_g);
1.1       root      261: 
                    262:     // Update equipment word bits for floppy
1.1.1.4   root      263:     if (FloppyCount == 1) {
1.1       root      264:         // 1 drive, ready for boot
                    265:         SETBITS_BDA(equipment_list_flags, 0x01);
                    266:         SET_BDA(floppy_harddisk_info, 0x07);
1.1.1.4   root      267:     } else if (FloppyCount >= 2) {
1.1       root      268:         // 2 drives, ready for boot
                    269:         SETBITS_BDA(equipment_list_flags, 0x41);
                    270:         SET_BDA(floppy_harddisk_info, 0x77);
                    271:     }
                    272: }
                    273: 
                    274: 
                    275: /****************************************************************
                    276:  * 16bit calling interface
                    277:  ****************************************************************/
                    278: 
1.1.1.6 ! root      279: static int
        !           280: process_scsi_op(struct disk_op_s *op)
        !           281: {
        !           282:     if (!CONFIG_VIRTIO_SCSI && !CONFIG_USB_MSC)
        !           283:         return 0;
        !           284:     switch (op->command) {
        !           285:     case CMD_READ:
        !           286:         return cdb_read(op);
        !           287:     case CMD_WRITE:
        !           288:         return cdb_write(op);
        !           289:     case CMD_FORMAT:
        !           290:     case CMD_RESET:
        !           291:     case CMD_ISREADY:
        !           292:     case CMD_VERIFY:
        !           293:     case CMD_SEEK:
        !           294:         return DISK_RET_SUCCESS;
        !           295:     default:
        !           296:         op->count = 0;
        !           297:         return DISK_RET_EPARAM;
        !           298:     }
        !           299: }
        !           300: 
1.1       root      301: // Execute a disk_op request.
                    302: int
                    303: process_op(struct disk_op_s *op)
                    304: {
1.1.1.3   root      305:     ASSERT16();
1.1       root      306:     u8 type = GET_GLOBAL(op->drive_g->type);
                    307:     switch (type) {
                    308:     case DTYPE_FLOPPY:
                    309:         return process_floppy_op(op);
                    310:     case DTYPE_ATA:
                    311:         return process_ata_op(op);
                    312:     case DTYPE_ATAPI:
                    313:         return process_atapi_op(op);
                    314:     case DTYPE_RAMDISK:
                    315:         return process_ramdisk_op(op);
                    316:     case DTYPE_CDEMU:
                    317:         return process_cdemu_op(op);
1.1.1.6 ! root      318:     case DTYPE_VIRTIO_BLK:
        !           319:         return process_virtio_blk_op(op);
1.1.1.4   root      320:     case DTYPE_AHCI:
1.1.1.6 ! root      321:         return process_ahci_op(op);
        !           322:     case DTYPE_USB:
        !           323:     case DTYPE_VIRTIO_SCSI:
        !           324:         return process_scsi_op(op);
1.1       root      325:     default:
                    326:         op->count = 0;
                    327:         return DISK_RET_EPARAM;
                    328:     }
                    329: }
                    330: 
                    331: // Execute a "disk_op_s" request - this runs on a stack in the ebda.
                    332: static int
                    333: __send_disk_op(struct disk_op_s *op_far, u16 op_seg)
                    334: {
                    335:     struct disk_op_s dop;
                    336:     memcpy_far(GET_SEG(SS), &dop
                    337:                , op_seg, op_far
                    338:                , sizeof(dop));
                    339: 
                    340:     dprintf(DEBUG_HDL_13, "disk_op d=%p lba=%d buf=%p count=%d cmd=%d\n"
                    341:             , dop.drive_g, (u32)dop.lba, dop.buf_fl
                    342:             , dop.count, dop.command);
                    343: 
                    344:     int status = process_op(&dop);
                    345: 
                    346:     // Update count with total sectors transferred.
                    347:     SET_FARVAR(op_seg, op_far->count, dop.count);
                    348: 
                    349:     return status;
                    350: }
                    351: 
                    352: // Execute a "disk_op_s" request by jumping to a stack in the ebda.
                    353: int
                    354: send_disk_op(struct disk_op_s *op)
                    355: {
1.1.1.3   root      356:     ASSERT16();
1.1       root      357:     if (! CONFIG_DRIVES)
                    358:         return -1;
                    359: 
1.1.1.3   root      360:     return stack_hop((u32)op, GET_SEG(SS), __send_disk_op);
1.1       root      361: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.