1 |
/* |
/* |
2 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: diskimage.c,v 1.98 2005/09/27 23:55:43 debug Exp $ |
* $Id: diskimage.c,v 1.111 2006/08/14 17:27:45 debug Exp $ |
29 |
* |
* |
30 |
* Disk image support. |
* Disk image support. |
31 |
* |
* |
53 |
#include "misc.h" |
#include "misc.h" |
54 |
|
|
55 |
|
|
56 |
extern int quiet_mode; |
/* #define debug fatal */ |
57 |
|
|
58 |
extern int single_step; |
extern int single_step; |
59 |
|
|
60 |
static char *diskimage_types[] = DISKIMAGE_TYPES; |
static char *diskimage_types[] = DISKIMAGE_TYPES; |
451 |
|
|
452 |
/* Warn about non-complete data transfers: */ |
/* Warn about non-complete data transfers: */ |
453 |
if (lendone != (ssize_t)len) { |
if (lendone != (ssize_t)len) { |
454 |
|
#ifdef UNSTABLE_DEVEL |
455 |
fatal("[ diskimage__internal_access(): disk_id %i, offset %lli" |
fatal("[ diskimage__internal_access(): disk_id %i, offset %lli" |
456 |
", transfer not completed. len=%i, len_done=%i ]\n", |
", transfer not completed. len=%i, len_done=%i ]\n", |
457 |
d->id, (long long)offset, (int)len, (int)lendone); |
d->id, (long long)offset, (int)len, (int)lendone); |
458 |
|
#endif |
459 |
return 0; |
return 0; |
460 |
} |
} |
461 |
|
|
482 |
struct scsi_transfer *xferp) |
struct scsi_transfer *xferp) |
483 |
{ |
{ |
484 |
char namebuf[16]; |
char namebuf[16]; |
485 |
int retlen, i; |
int retlen, i, q; |
486 |
uint64_t size; |
uint64_t size; |
487 |
int64_t ofs; |
int64_t ofs; |
488 |
int pagecode; |
int pagecode; |
526 |
fatal(" %02x", xferp->cmd[i]); |
fatal(" %02x", xferp->cmd[i]); |
527 |
fatal("\n"); |
fatal("\n"); |
528 |
if (xferp->cmd_len > 7 && xferp->cmd[5] == 0x11) |
if (xferp->cmd_len > 7 && xferp->cmd[5] == 0x11) |
529 |
single_step = 1; |
single_step = ENTER_SINGLE_STEPPING; |
530 |
#endif |
#endif |
531 |
|
|
532 |
#if 0 |
#if 0 |
594 |
|
|
595 |
/* These are padded with spaces: */ |
/* These are padded with spaces: */ |
596 |
|
|
597 |
memcpy(xferp->data_in+8, "EMULATED", 8); |
memcpy(xferp->data_in+8, "GXemul ", 8); |
598 |
if (diskimage_getname(cpu->machine, id, |
if (diskimage_getname(cpu->machine, id, |
599 |
type, namebuf, sizeof(namebuf))) { |
type, namebuf, sizeof(namebuf))) { |
600 |
int i; |
size_t i; |
601 |
for (i=0; i<sizeof(namebuf); i++) |
for (i=0; i<sizeof(namebuf); i++) |
602 |
if (namebuf[i] == 0) { |
if (namebuf[i] == 0) { |
603 |
for (; i<sizeof(namebuf); i++) |
for (; i<sizeof(namebuf); i++) |
607 |
memcpy(xferp->data_in+16, namebuf, 16); |
memcpy(xferp->data_in+16, namebuf, 16); |
608 |
} else |
} else |
609 |
memcpy(xferp->data_in+16, "DISK ", 16); |
memcpy(xferp->data_in+16, "DISK ", 16); |
610 |
memcpy(xferp->data_in+32, "0000", 4); |
memcpy(xferp->data_in+32, "0 ", 4); |
611 |
|
|
612 |
/* |
/* |
613 |
* Some Ultrix kernels want specific responses from |
* Some Ultrix kernels want specific responses from |
614 |
* the drives. |
* the drives. |
615 |
*/ |
*/ |
616 |
|
|
617 |
if (machine->machine_type == MACHINE_DEC) { |
if (machine->machine_type == MACHINE_PMAX) { |
618 |
/* DEC, RZ25 (rev 0900) = 832527 sectors */ |
/* DEC, RZ25 (rev 0900) = 832527 sectors */ |
619 |
/* DEC, RZ58 (rev 2000) = 2698061 sectors */ |
/* DEC, RZ58 (rev 2000) = 2698061 sectors */ |
620 |
memcpy(xferp->data_in+8, "DEC ", 8); |
memcpy(xferp->data_in+8, "DEC ", 8); |
626 |
if (d->is_a_cdrom) { |
if (d->is_a_cdrom) { |
627 |
xferp->data_in[0] = 0x05; /* 0x05 = CD-ROM */ |
xferp->data_in[0] = 0x05; /* 0x05 = CD-ROM */ |
628 |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
629 |
memcpy(xferp->data_in+16, "CD-ROM ", 16); |
/* memcpy(xferp->data_in+16, "CD-ROM ", 16);*/ |
630 |
|
|
631 |
if (machine->machine_type == MACHINE_DEC) { |
if (machine->machine_type == MACHINE_PMAX) { |
632 |
/* SONY, CD-ROM: */ |
/* SONY, CD-ROM: */ |
633 |
memcpy(xferp->data_in+8, "SONY ", 8); |
memcpy(xferp->data_in+8, "SONY ", 8); |
634 |
memcpy(xferp->data_in+16, |
memcpy(xferp->data_in+16, |
639 |
memcpy(xferp->data_in+16, |
memcpy(xferp->data_in+16, |
640 |
"RRD42 (C) DEC ", 16); |
"RRD42 (C) DEC ", 16); |
641 |
memcpy(xferp->data_in+32, "4.5d", 4); |
memcpy(xferp->data_in+32, "4.5d", 4); |
642 |
} else { |
} else if (machine->machine_type == MACHINE_ARC) { |
643 |
/* NEC, CD-ROM: */ |
/* NEC, CD-ROM: */ |
644 |
memcpy(xferp->data_in+8, "NEC ", 8); |
memcpy(xferp->data_in+8, "NEC ", 8); |
645 |
memcpy(xferp->data_in+16, |
memcpy(xferp->data_in+16, |
654 |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
655 |
memcpy(xferp->data_in+16, "TAPE ", 16); |
memcpy(xferp->data_in+16, "TAPE ", 16); |
656 |
|
|
657 |
if (machine->machine_type == MACHINE_DEC) { |
if (machine->machine_type == MACHINE_PMAX) { |
658 |
/* |
/* |
659 |
* TODO: find out if these are correct. |
* TODO: find out if these are correct. |
660 |
* |
* |
709 |
break; |
break; |
710 |
|
|
711 |
case SCSICMD_MODE_SENSE: |
case SCSICMD_MODE_SENSE: |
712 |
|
case SCSICMD_MODE_SENSE10: |
713 |
debug("MODE_SENSE"); |
debug("MODE_SENSE"); |
714 |
|
q = 4; retlen = xferp->cmd[4]; |
715 |
if (xferp->cmd_len != 6) |
switch (xferp->cmd_len) { |
716 |
fatal(" (unimplemented mode_sense len=%i)", |
case 6: break; |
717 |
|
case 10:q = 8; |
718 |
|
retlen = xferp->cmd[7] * 256 + xferp->cmd[8]; |
719 |
|
break; |
720 |
|
default:fatal(" (unimplemented mode_sense len=%i)", |
721 |
xferp->cmd_len); |
xferp->cmd_len); |
722 |
|
} |
|
retlen = xferp->cmd[4]; |
|
723 |
|
|
724 |
/* |
/* |
725 |
* NOTE/TODO: This code doesn't handle too short retlens |
* NOTE/TODO: This code doesn't handle too short retlens |
754 |
xferp->data_in[3] = 8 * 1; /* block descriptor |
xferp->data_in[3] = 8 * 1; /* block descriptor |
755 |
length: 1 page (?) */ |
length: 1 page (?) */ |
756 |
|
|
757 |
/* TODO: update this when implementing 10-byte commands: */ |
xferp->data_in[q+0] = 0x00; /* density code */ |
758 |
xferp->data_in[4] = 0x00; /* density code */ |
xferp->data_in[q+1] = 0; /* nr of blocks, high */ |
759 |
xferp->data_in[5] = 0; /* nr of blocks, high */ |
xferp->data_in[q+2] = 0; /* nr of blocks, mid */ |
760 |
xferp->data_in[6] = 0; /* nr of blocks, mid */ |
xferp->data_in[q+3] = 0; /* nr of blocks, low */ |
761 |
xferp->data_in[7] = 0; /* nr of blocks, low */ |
xferp->data_in[q+4] = 0x00; /* reserved */ |
762 |
xferp->data_in[8] = 0x00; /* reserved */ |
xferp->data_in[q+5] = (d->logical_block_size >> 16) & 255; |
763 |
xferp->data_in[9] = (d->logical_block_size >> 16) & 255; |
xferp->data_in[q+6] = (d->logical_block_size >> 8) & 255; |
764 |
xferp->data_in[10] = (d->logical_block_size >> 8) & 255; |
xferp->data_in[q+7] = d->logical_block_size & 255; |
765 |
xferp->data_in[11] = d->logical_block_size & 255; |
q += 8; |
766 |
|
|
767 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
768 |
|
|
774 |
/* TODO: Nothing here? */ |
/* TODO: Nothing here? */ |
775 |
break; |
break; |
776 |
case 1: /* read-write error recovery page */ |
case 1: /* read-write error recovery page */ |
777 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
778 |
xferp->data_in[12 + 1] = 10; |
xferp->data_in[q + 1] = 10; |
779 |
break; |
break; |
780 |
case 3: /* format device page */ |
case 3: /* format device page */ |
781 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
782 |
xferp->data_in[12 + 1] = 22; |
xferp->data_in[q + 1] = 22; |
783 |
|
|
784 |
/* 10,11 = sectors per track */ |
/* 10,11 = sectors per track */ |
785 |
xferp->data_in[12 + 10] = 0; |
xferp->data_in[q + 10] = 0; |
786 |
xferp->data_in[12 + 11] = d->sectors_per_track; |
xferp->data_in[q + 11] = d->sectors_per_track; |
787 |
|
|
788 |
/* 12,13 = physical sector size */ |
/* 12,13 = physical sector size */ |
789 |
xferp->data_in[12 + 12] = |
xferp->data_in[q + 12] = |
790 |
(d->logical_block_size >> 8) & 255; |
(d->logical_block_size >> 8) & 255; |
791 |
xferp->data_in[12 + 13] = d->logical_block_size & 255; |
xferp->data_in[q + 13] = d->logical_block_size & 255; |
792 |
break; |
break; |
793 |
case 4: /* rigid disk geometry page */ |
case 4: /* rigid disk geometry page */ |
794 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
795 |
xferp->data_in[12 + 1] = 22; |
xferp->data_in[q + 1] = 22; |
796 |
xferp->data_in[12 + 2] = (d->ncyls >> 16) & 255; |
xferp->data_in[q + 2] = (d->ncyls >> 16) & 255; |
797 |
xferp->data_in[12 + 3] = (d->ncyls >> 8) & 255; |
xferp->data_in[q + 3] = (d->ncyls >> 8) & 255; |
798 |
xferp->data_in[12 + 4] = d->ncyls & 255; |
xferp->data_in[q + 4] = d->ncyls & 255; |
799 |
xferp->data_in[12 + 5] = d->heads; |
xferp->data_in[q + 5] = d->heads; |
800 |
|
|
801 |
xferp->data_in[12 + 20] = (d->rpms >> 8) & 255; |
xferp->data_in[q + 20] = (d->rpms >> 8) & 255; |
802 |
xferp->data_in[12 + 21] = d->rpms & 255; |
xferp->data_in[q + 21] = d->rpms & 255; |
803 |
break; |
break; |
804 |
case 5: /* flexible disk page */ |
case 5: /* flexible disk page */ |
805 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
806 |
xferp->data_in[12 + 1] = 0x1e; |
xferp->data_in[q + 1] = 0x1e; |
807 |
|
|
808 |
/* 2,3 = transfer rate */ |
/* 2,3 = transfer rate */ |
809 |
xferp->data_in[12 + 2] = ((5000) >> 8) & 255; |
xferp->data_in[q + 2] = ((5000) >> 8) & 255; |
810 |
xferp->data_in[12 + 3] = (5000) & 255; |
xferp->data_in[q + 3] = (5000) & 255; |
811 |
|
|
812 |
xferp->data_in[12 + 4] = d->heads; |
xferp->data_in[q + 4] = d->heads; |
813 |
xferp->data_in[12 + 5] = d->sectors_per_track; |
xferp->data_in[q + 5] = d->sectors_per_track; |
814 |
|
|
815 |
/* 6,7 = data bytes per sector */ |
/* 6,7 = data bytes per sector */ |
816 |
xferp->data_in[12 + 6] = (d->logical_block_size >> 8) |
xferp->data_in[q + 6] = (d->logical_block_size >> 8) |
817 |
& 255; |
& 255; |
818 |
xferp->data_in[12 + 7] = d->logical_block_size & 255; |
xferp->data_in[q + 7] = d->logical_block_size & 255; |
819 |
|
|
820 |
xferp->data_in[12 + 8] = (d->ncyls >> 8) & 255; |
xferp->data_in[q + 8] = (d->ncyls >> 8) & 255; |
821 |
xferp->data_in[12 + 9] = d->ncyls & 255; |
xferp->data_in[q + 9] = d->ncyls & 255; |
822 |
|
|
823 |
xferp->data_in[12 + 28] = (d->rpms >> 8) & 255; |
xferp->data_in[q + 28] = (d->rpms >> 8) & 255; |
824 |
xferp->data_in[12 + 29] = d->rpms & 255; |
xferp->data_in[q + 29] = d->rpms & 255; |
825 |
break; |
break; |
826 |
default: |
default: |
827 |
fatal("[ MODE_SENSE for page %i is not yet " |
fatal("[ MODE_SENSE for page %i is not yet " |
899 |
* blocks to transfer. (NOTE: If the value is |
* blocks to transfer. (NOTE: If the value is |
900 |
* 0, this means 0, not 65536. :-) |
* 0, this means 0, not 65536. :-) |
901 |
*/ |
*/ |
902 |
ofs = (xferp->cmd[2] << 24) + (xferp->cmd[3] |
ofs = ((uint64_t)xferp->cmd[2] << 24) + |
903 |
<< 16) + (xferp->cmd[4] << 8) + |
(xferp->cmd[3] << 16) + (xferp->cmd[4] << 8) |
904 |
xferp->cmd[5]; |
+ xferp->cmd[5]; |
905 |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
906 |
} |
} |
907 |
|
|
977 |
* transfer. (NOTE: If the value is 0 this means 0, |
* transfer. (NOTE: If the value is 0 this means 0, |
978 |
* not 65536.) |
* not 65536.) |
979 |
*/ |
*/ |
980 |
ofs = (xferp->cmd[2] << 24) + (xferp->cmd[3] << 16) + |
ofs = ((uint64_t)xferp->cmd[2] << 24) + |
981 |
(xferp->cmd[4] << 8) + xferp->cmd[5]; |
(xferp->cmd[3] << 16) + (xferp->cmd[4] << 8) + |
982 |
|
xferp->cmd[5]; |
983 |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
984 |
} |
} |
985 |
|
|
1027 |
if (xferp->cmd_len != 6) |
if (xferp->cmd_len != 6) |
1028 |
debug(" (weird len=%i)", xferp->cmd_len); |
debug(" (weird len=%i)", xferp->cmd_len); |
1029 |
|
|
1030 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<(ssize_t)xferp->cmd_len; i++) |
1031 |
debug(" %02x", xferp->cmd[i]); |
debug(" %02x", xferp->cmd[i]); |
1032 |
|
|
1033 |
/* TODO: actualy care about cmd[] */ |
/* TODO: actualy care about cmd[] */ |
1236 |
scsi_transfer_allocbuf(&xferp->data_in_len, |
scsi_transfer_allocbuf(&xferp->data_in_len, |
1237 |
&xferp->data_in, retlen, 1); |
&xferp->data_in, retlen, 1); |
1238 |
|
|
1239 |
/* TODO */ |
xferp->data_in[0] = 0; |
1240 |
|
xferp->data_in[1] = 10; |
1241 |
|
xferp->data_in[2] = 0; /* First track. */ |
1242 |
|
xferp->data_in[3] = 0; /* Last track. */ |
1243 |
|
|
1244 |
|
/* Track 0 data: */ |
1245 |
|
xferp->data_in[4] = 0x00; /* Reserved. */ |
1246 |
|
xferp->data_in[5] = 0x04; /* ADR + CTRL: |
1247 |
|
Data, not audio */ |
1248 |
|
xferp->data_in[6] = 0x00; /* Track nr */ |
1249 |
|
xferp->data_in[7] = 0x00; /* Reserved */ |
1250 |
|
/* 8..11 = absolute CDROM address */ |
1251 |
|
|
1252 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
1253 |
break; |
break; |
1288 |
} else { |
} else { |
1289 |
int i; |
int i; |
1290 |
fatal("[ unknown MODE_SELECT: cmd ="); |
fatal("[ unknown MODE_SELECT: cmd ="); |
1291 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<(ssize_t)xferp->cmd_len; i++) |
1292 |
fatal(" %02x", xferp->cmd[i]); |
fatal(" %02x", xferp->cmd[i]); |
1293 |
fatal(", data_out ="); |
fatal(", data_out ="); |
1294 |
for (i=0; i<xferp->data_out_len; i++) |
for (i=0; i<(ssize_t)xferp->data_out_len; i++) |
1295 |
fatal(" %02x", xferp->data_out[i]); |
fatal(" %02x", xferp->data_out[i]); |
1296 |
fatal(" ]"); |
fatal(" ]"); |
1297 |
} |
} |
1300 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
1301 |
break; |
break; |
1302 |
|
|
1303 |
case 0x1e: |
case SCSICMD_PREVENT_ALLOW_REMOVE: |
1304 |
debug("[ SCSI 0x%02x: TODO ]\n", xferp->cmd[0]); |
debug("[ SCSI 0x%02x Prevent/allow medium removal: " |
1305 |
|
"TODO ]\n", xferp->cmd[0]); |
|
/* TODO */ |
|
1306 |
|
|
1307 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
1308 |
break; |
break; |
1310 |
case 0xbd: |
case 0xbd: |
1311 |
fatal("[ SCSI 0x%02x (len %i), TODO: ", xferp->cmd[0], |
fatal("[ SCSI 0x%02x (len %i), TODO: ", xferp->cmd[0], |
1312 |
xferp->cmd_len); |
xferp->cmd_len); |
1313 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<(ssize_t)xferp->cmd_len; i++) |
1314 |
fatal(" %02x", xferp->cmd[i]); |
fatal(" %02x", xferp->cmd[i]); |
1315 |
fatal(" ]\n"); |
fatal(" ]\n"); |
1316 |
|
|
1501 |
d2->next = d; |
d2->next = d; |
1502 |
} |
} |
1503 |
|
|
1504 |
d->type = DISKIMAGE_SCSI; |
/* Default to IDE disks... */ |
1505 |
|
d->type = DISKIMAGE_IDE; |
1506 |
|
|
1507 |
/* Special cases: some machines usually have FLOPPY/IDE, not SCSI: */ |
/* ... but some machines use SCSI by default: */ |
1508 |
if (machine->arch == ARCH_X86 || |
if (machine->machine_type == MACHINE_PMAX || |
1509 |
machine->machine_type == MACHINE_COBALT || |
machine->machine_type == MACHINE_ARC) |
1510 |
machine->machine_type == MACHINE_EVBMIPS || |
d->type = DISKIMAGE_SCSI; |
|
machine->machine_type == MACHINE_HPCMIPS || |
|
|
machine->machine_type == MACHINE_CATS || |
|
|
machine->machine_type == MACHINE_NETWINDER || |
|
|
machine->machine_type == MACHINE_PS2) |
|
|
d->type = DISKIMAGE_IDE; |
|
1511 |
|
|
1512 |
if (prefix_i + prefix_f + prefix_s > 1) { |
if (prefix_i + prefix_f + prefix_s > 1) { |
1513 |
fprintf(stderr, "Invalid disk image prefix(es). You can" |
fprintf(stderr, "Invalid disk image prefix(es). You can" |
1560 |
*/ |
*/ |
1561 |
|
|
1562 |
#if 0 |
#if 0 |
1563 |
if (machine->machine_type == MACHINE_DEC) |
if (machine->machine_type == MACHINE_PMAX) |
1564 |
d->logical_block_size = 512; |
d->logical_block_size = 512; |
1565 |
else |
else |
1566 |
d->logical_block_size = 2048; |
d->logical_block_size = 2048; |
1774 |
*/ |
*/ |
1775 |
void diskimage_dump_info(struct machine *machine) |
void diskimage_dump_info(struct machine *machine) |
1776 |
{ |
{ |
1777 |
int iadd=4; |
int iadd = DEBUG_INDENTATION; |
1778 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1779 |
|
|
1780 |
while (d != NULL) { |
while (d != NULL) { |