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.81 2005/04/04 21:50:05 debug Exp $ |
* $Id: diskimage.c,v 1.109 2006/05/06 08:42:48 debug Exp $ |
29 |
* |
* |
30 |
* Disk image support. |
* Disk image support. |
31 |
* |
* |
36 |
* that return feof (which results in a filemark). This is probably |
* that return feof (which results in a filemark). This is probably |
37 |
* trivial to fix, but I don't feel like it right now. |
* trivial to fix, but I don't feel like it right now. |
38 |
* |
* |
39 |
* TODO: Non-SCSI disk images? |
* TODO: diskimage_remove()? This would be useful for floppies in PC-style |
40 |
* |
* machines, where disks may need to be swapped during boot etc. |
|
* TODO: diskimage_remove() ? |
|
|
* Actually test diskimage_access() to see that it works. |
|
41 |
*/ |
*/ |
42 |
|
|
43 |
#include <stdio.h> |
#include <stdio.h> |
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; |
61 |
|
|
62 |
static struct scsi_transfer *first_free_scsi_transfer_alloc = NULL; |
static struct scsi_transfer *first_free_scsi_transfer_alloc = NULL; |
63 |
|
|
209 |
/* |
/* |
210 |
* diskimage_exist(): |
* diskimage_exist(): |
211 |
* |
* |
212 |
* Returns 1 if the specified SCSI id exists, 0 otherwise. |
* Returns 1 if the specified disk id (for a specific type) exists, 0 |
213 |
|
* otherwise. |
214 |
*/ |
*/ |
215 |
int diskimage_exist(struct machine *machine, int scsi_id) |
int diskimage_exist(struct machine *machine, int id, int type) |
216 |
{ |
{ |
217 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
218 |
|
|
219 |
while (d != NULL) { |
while (d != NULL) { |
220 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
221 |
return 1; |
return 1; |
222 |
d = d->next; |
d = d->next; |
223 |
} |
} |
257 |
|
|
258 |
d->total_size = size; |
d->total_size = size; |
259 |
d->ncyls = d->total_size / 1048576; |
d->ncyls = d->total_size / 1048576; |
260 |
|
|
261 |
|
/* TODO: There is a mismatch between d->ncyls and d->cylinders, |
262 |
|
SCSI-based stuff usually doesn't care. TODO: Fix this. */ |
263 |
} |
} |
264 |
|
|
265 |
|
|
266 |
/* |
/* |
267 |
* diskimage_getsize(): |
* diskimage_getsize(): |
268 |
* |
* |
269 |
* Returns -1 if the specified SCSI id does not exists, otherwise |
* Returns -1 if the specified disk id/type does not exists, otherwise |
270 |
* the size of the disk image is returned. |
* the size of the disk image is returned. |
271 |
*/ |
*/ |
272 |
int64_t diskimage_getsize(struct machine *machine, int scsi_id) |
int64_t diskimage_getsize(struct machine *machine, int id, int type) |
273 |
{ |
{ |
274 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
275 |
|
|
276 |
while (d != NULL) { |
while (d != NULL) { |
277 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
278 |
return d->total_size; |
return d->total_size; |
279 |
d = d->next; |
d = d->next; |
280 |
} |
} |
283 |
|
|
284 |
|
|
285 |
/* |
/* |
286 |
|
* diskimage_getchs(): |
287 |
|
* |
288 |
|
* Returns the current CHS values of a disk image. |
289 |
|
*/ |
290 |
|
void diskimage_getchs(struct machine *machine, int id, int type, |
291 |
|
int *c, int *h, int *s) |
292 |
|
{ |
293 |
|
struct diskimage *d = machine->first_diskimage; |
294 |
|
|
295 |
|
while (d != NULL) { |
296 |
|
if (d->type == type && d->id == id) { |
297 |
|
*c = d->cylinders; |
298 |
|
*h = d->heads; |
299 |
|
*s = d->sectors_per_track; |
300 |
|
return; |
301 |
|
} |
302 |
|
d = d->next; |
303 |
|
} |
304 |
|
fatal("diskimage_getchs(): disk id %i (type %i) not found?\n", |
305 |
|
id, diskimage_types[type]); |
306 |
|
exit(1); |
307 |
|
} |
308 |
|
|
309 |
|
|
310 |
|
/* |
311 |
* diskimage__return_default_status_and_message(): |
* diskimage__return_default_status_and_message(): |
312 |
* |
* |
313 |
* Set the status and msg_in parts of a scsi_transfer struct |
* Set the status and msg_in parts of a scsi_transfer struct |
410 |
static int diskimage__internal_access(struct diskimage *d, int writeflag, |
static int diskimage__internal_access(struct diskimage *d, int writeflag, |
411 |
off_t offset, unsigned char *buf, size_t len) |
off_t offset, unsigned char *buf, size_t len) |
412 |
{ |
{ |
413 |
size_t lendone; |
ssize_t lendone; |
414 |
int res; |
int res; |
415 |
|
|
416 |
if (buf == NULL) { |
if (buf == NULL) { |
476 |
* 1 if otherwise ok, |
* 1 if otherwise ok, |
477 |
* 0 on error. |
* 0 on error. |
478 |
*/ |
*/ |
479 |
int diskimage_scsicommand(struct cpu *cpu, int scsi_id, |
int diskimage_scsicommand(struct cpu *cpu, int id, int type, |
480 |
struct scsi_transfer *xferp) |
struct scsi_transfer *xferp) |
481 |
{ |
{ |
482 |
int retlen, i; |
char namebuf[16]; |
483 |
|
int retlen, i, q; |
484 |
uint64_t size; |
uint64_t size; |
485 |
int64_t ofs; |
int64_t ofs; |
486 |
int pagecode; |
int pagecode; |
494 |
|
|
495 |
d = machine->first_diskimage; |
d = machine->first_diskimage; |
496 |
while (d != NULL) { |
while (d != NULL) { |
497 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
498 |
break; |
break; |
499 |
d = d->next; |
d = d->next; |
500 |
} |
} |
501 |
if (d == NULL) { |
if (d == NULL) { |
502 |
fprintf(stderr, "[ diskimage_scsicommand(): SCSI disk" |
fprintf(stderr, "[ diskimage_scsicommand(): %s " |
503 |
" with id %i not connected? ]\n", scsi_id); |
" id %i not connected? ]\n", diskimage_types[type], id); |
504 |
} |
} |
505 |
|
|
506 |
if (xferp->cmd == NULL) { |
if (xferp->cmd == NULL) { |
515 |
} |
} |
516 |
|
|
517 |
debug("[ diskimage_scsicommand(id=%i) cmd=0x%02x: ", |
debug("[ diskimage_scsicommand(id=%i) cmd=0x%02x: ", |
518 |
scsi_id, xferp->cmd[0]); |
id, xferp->cmd[0]); |
519 |
|
|
520 |
#if 0 |
#if 0 |
521 |
fatal("[ diskimage_scsicommand(id=%i) cmd=0x%02x len=%i:", |
fatal("[ diskimage_scsicommand(id=%i) cmd=0x%02x len=%i:", |
522 |
scsi_id, xferp->cmd[0], xferp->cmd_len); |
id, xferp->cmd[0], xferp->cmd_len); |
523 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<xferp->cmd_len; i++) |
524 |
fatal(" %02x", xferp->cmd[i]); |
fatal(" %02x", xferp->cmd[i]); |
525 |
fatal("\n"); |
fatal("\n"); |
534 |
f = fopen("scsi_log.txt", "w"); |
f = fopen("scsi_log.txt", "w"); |
535 |
if (f != NULL) { |
if (f != NULL) { |
536 |
int i; |
int i; |
537 |
fprintf(f, "id=%i cmd =", scsi_id); |
fprintf(f, "id=%i cmd =", id); |
538 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<xferp->cmd_len; i++) |
539 |
fprintf(f, " %02x", xferp->cmd[i]); |
fprintf(f, " %02x", xferp->cmd[i]); |
540 |
fprintf(f, "\n"); |
fprintf(f, "\n"); |
590 |
xferp->data_in[6] = 0x04; /* ACKREQQ */ |
xferp->data_in[6] = 0x04; /* ACKREQQ */ |
591 |
xferp->data_in[7] = 0x60; /* WBus32, WBus16 */ |
xferp->data_in[7] = 0x60; /* WBus32, WBus16 */ |
592 |
|
|
593 |
/* These must be padded with spaces: */ |
/* These are padded with spaces: */ |
594 |
memcpy(xferp->data_in+8, "FAKE ", 8); |
|
595 |
memcpy(xferp->data_in+16, "DISK ", 16); |
memcpy(xferp->data_in+8, "GXemul ", 8); |
596 |
memcpy(xferp->data_in+32, "V0.0", 4); |
if (diskimage_getname(cpu->machine, id, |
597 |
|
type, namebuf, sizeof(namebuf))) { |
598 |
|
size_t i; |
599 |
|
for (i=0; i<sizeof(namebuf); i++) |
600 |
|
if (namebuf[i] == 0) { |
601 |
|
for (; i<sizeof(namebuf); i++) |
602 |
|
namebuf[i] = ' '; |
603 |
|
break; |
604 |
|
} |
605 |
|
memcpy(xferp->data_in+16, namebuf, 16); |
606 |
|
} else |
607 |
|
memcpy(xferp->data_in+16, "DISK ", 16); |
608 |
|
memcpy(xferp->data_in+32, "0 ", 4); |
609 |
|
|
610 |
/* |
/* |
611 |
* Some Ultrix kernels want specific responses from |
* Some Ultrix kernels want specific responses from |
612 |
* the drives. |
* the drives. |
613 |
*/ |
*/ |
614 |
|
|
615 |
if (machine->machine_type == MACHINE_DEC) { |
if (machine->machine_type == MACHINE_PMAX) { |
616 |
/* DEC, RZ25 (rev 0900) = 832527 sectors */ |
/* DEC, RZ25 (rev 0900) = 832527 sectors */ |
617 |
/* DEC, RZ58 (rev 2000) = 2698061 sectors */ |
/* DEC, RZ58 (rev 2000) = 2698061 sectors */ |
618 |
memcpy(xferp->data_in+8, "DEC ", 8); |
memcpy(xferp->data_in+8, "DEC ", 8); |
624 |
if (d->is_a_cdrom) { |
if (d->is_a_cdrom) { |
625 |
xferp->data_in[0] = 0x05; /* 0x05 = CD-ROM */ |
xferp->data_in[0] = 0x05; /* 0x05 = CD-ROM */ |
626 |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
627 |
memcpy(xferp->data_in+16, "CD-ROM ", 16); |
/* memcpy(xferp->data_in+16, "CD-ROM ", 16);*/ |
628 |
|
|
629 |
if (machine->machine_type == MACHINE_DEC) { |
if (machine->machine_type == MACHINE_PMAX) { |
630 |
/* SONY, CD-ROM: */ |
/* SONY, CD-ROM: */ |
631 |
memcpy(xferp->data_in+8, "SONY ", 8); |
memcpy(xferp->data_in+8, "SONY ", 8); |
632 |
memcpy(xferp->data_in+16, |
memcpy(xferp->data_in+16, |
637 |
memcpy(xferp->data_in+16, |
memcpy(xferp->data_in+16, |
638 |
"RRD42 (C) DEC ", 16); |
"RRD42 (C) DEC ", 16); |
639 |
memcpy(xferp->data_in+32, "4.5d", 4); |
memcpy(xferp->data_in+32, "4.5d", 4); |
640 |
} else { |
} else if (machine->machine_type == MACHINE_ARC) { |
641 |
/* NEC, CD-ROM: */ |
/* NEC, CD-ROM: */ |
642 |
memcpy(xferp->data_in+8, "NEC ", 8); |
memcpy(xferp->data_in+8, "NEC ", 8); |
643 |
memcpy(xferp->data_in+16, |
memcpy(xferp->data_in+16, |
652 |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
xferp->data_in[1] = 0x80; /* 0x80 = removable */ |
653 |
memcpy(xferp->data_in+16, "TAPE ", 16); |
memcpy(xferp->data_in+16, "TAPE ", 16); |
654 |
|
|
655 |
if (machine->machine_type == MACHINE_DEC) { |
if (machine->machine_type == MACHINE_PMAX) { |
656 |
/* |
/* |
657 |
* TODO: find out if these are correct. |
* TODO: find out if these are correct. |
658 |
* |
* |
707 |
break; |
break; |
708 |
|
|
709 |
case SCSICMD_MODE_SENSE: |
case SCSICMD_MODE_SENSE: |
710 |
|
case SCSICMD_MODE_SENSE10: |
711 |
debug("MODE_SENSE"); |
debug("MODE_SENSE"); |
712 |
|
q = 4; retlen = xferp->cmd[4]; |
713 |
if (xferp->cmd_len != 6) |
switch (xferp->cmd_len) { |
714 |
fatal(" (unimplemented mode_sense len=%i)", |
case 6: break; |
715 |
|
case 10:q = 8; |
716 |
|
retlen = xferp->cmd[7] * 256 + xferp->cmd[8]; |
717 |
|
break; |
718 |
|
default:fatal(" (unimplemented mode_sense len=%i)", |
719 |
xferp->cmd_len); |
xferp->cmd_len); |
720 |
|
} |
|
retlen = xferp->cmd[4]; |
|
721 |
|
|
722 |
/* |
/* |
723 |
* NOTE/TODO: This code doesn't handle too short retlens |
* NOTE/TODO: This code doesn't handle too short retlens |
740 |
|
|
741 |
pagecode = xferp->cmd[2] & 0x3f; |
pagecode = xferp->cmd[2] & 0x3f; |
742 |
|
|
743 |
debug("[ MODE SENSE id %i, pagecode=%i ]\n", scsi_id, pagecode); |
debug("[ MODE SENSE id %i, pagecode=%i ]\n", id, pagecode); |
744 |
|
|
745 |
/* 4 bytes of header for 6-byte command, |
/* 4 bytes of header for 6-byte command, |
746 |
8 bytes of header for 10-byte command. */ |
8 bytes of header for 10-byte command. */ |
752 |
xferp->data_in[3] = 8 * 1; /* block descriptor |
xferp->data_in[3] = 8 * 1; /* block descriptor |
753 |
length: 1 page (?) */ |
length: 1 page (?) */ |
754 |
|
|
755 |
/* TODO: update this when implementing 10-byte commands: */ |
xferp->data_in[q+0] = 0x00; /* density code */ |
756 |
xferp->data_in[4] = 0x00; /* density code */ |
xferp->data_in[q+1] = 0; /* nr of blocks, high */ |
757 |
xferp->data_in[5] = 0; /* nr of blocks, high */ |
xferp->data_in[q+2] = 0; /* nr of blocks, mid */ |
758 |
xferp->data_in[6] = 0; /* nr of blocks, mid */ |
xferp->data_in[q+3] = 0; /* nr of blocks, low */ |
759 |
xferp->data_in[7] = 0; /* nr of blocks, low */ |
xferp->data_in[q+4] = 0x00; /* reserved */ |
760 |
xferp->data_in[8] = 0x00; /* reserved */ |
xferp->data_in[q+5] = (d->logical_block_size >> 16) & 255; |
761 |
xferp->data_in[9] = (d->logical_block_size >> 16) & 255; |
xferp->data_in[q+6] = (d->logical_block_size >> 8) & 255; |
762 |
xferp->data_in[10] = (d->logical_block_size >> 8) & 255; |
xferp->data_in[q+7] = d->logical_block_size & 255; |
763 |
xferp->data_in[11] = d->logical_block_size & 255; |
q += 8; |
764 |
|
|
765 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
766 |
|
|
772 |
/* TODO: Nothing here? */ |
/* TODO: Nothing here? */ |
773 |
break; |
break; |
774 |
case 1: /* read-write error recovery page */ |
case 1: /* read-write error recovery page */ |
775 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
776 |
xferp->data_in[12 + 1] = 10; |
xferp->data_in[q + 1] = 10; |
777 |
break; |
break; |
778 |
case 3: /* format device page */ |
case 3: /* format device page */ |
779 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
780 |
xferp->data_in[12 + 1] = 22; |
xferp->data_in[q + 1] = 22; |
781 |
|
|
782 |
/* 10,11 = sectors per track */ |
/* 10,11 = sectors per track */ |
783 |
xferp->data_in[12 + 10] = 0; |
xferp->data_in[q + 10] = 0; |
784 |
xferp->data_in[12 + 11] = 1; /* TODO */ |
xferp->data_in[q + 11] = d->sectors_per_track; |
785 |
|
|
786 |
/* 12,13 = physical sector size */ |
/* 12,13 = physical sector size */ |
787 |
xferp->data_in[12 + 12] = |
xferp->data_in[q + 12] = |
788 |
(d->logical_block_size >> 8) & 255; |
(d->logical_block_size >> 8) & 255; |
789 |
xferp->data_in[12 + 13] = d->logical_block_size & 255; |
xferp->data_in[q + 13] = d->logical_block_size & 255; |
790 |
break; |
break; |
791 |
case 4: /* rigid disk geometry page */ |
case 4: /* rigid disk geometry page */ |
792 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
793 |
xferp->data_in[12 + 1] = 22; |
xferp->data_in[q + 1] = 22; |
794 |
xferp->data_in[12 + 2] = (d->ncyls >> 16) & 255; |
xferp->data_in[q + 2] = (d->ncyls >> 16) & 255; |
795 |
xferp->data_in[12 + 3] = (d->ncyls >> 8) & 255; |
xferp->data_in[q + 3] = (d->ncyls >> 8) & 255; |
796 |
xferp->data_in[12 + 4] = d->ncyls & 255; |
xferp->data_in[q + 4] = d->ncyls & 255; |
797 |
xferp->data_in[12 + 5] = 15; /* nr of heads */ |
xferp->data_in[q + 5] = d->heads; |
798 |
|
|
799 |
xferp->data_in[12 + 20] = (d->rpms >> 8) & 255; |
xferp->data_in[q + 20] = (d->rpms >> 8) & 255; |
800 |
xferp->data_in[12 + 21] = d->rpms & 255; |
xferp->data_in[q + 21] = d->rpms & 255; |
801 |
break; |
break; |
802 |
case 5: /* flexible disk page */ |
case 5: /* flexible disk page */ |
803 |
xferp->data_in[12 + 0] = pagecode; |
xferp->data_in[q + 0] = pagecode; |
804 |
xferp->data_in[12 + 1] = 0x1e; |
xferp->data_in[q + 1] = 0x1e; |
805 |
|
|
806 |
/* 2,3 = transfer rate */ |
/* 2,3 = transfer rate */ |
807 |
xferp->data_in[12 + 2] = ((5000) >> 8) & 255; |
xferp->data_in[q + 2] = ((5000) >> 8) & 255; |
808 |
xferp->data_in[12 + 3] = (5000) & 255; |
xferp->data_in[q + 3] = (5000) & 255; |
809 |
|
|
810 |
xferp->data_in[12 + 4] = 2; /* nr of heads */ |
xferp->data_in[q + 4] = d->heads; |
811 |
xferp->data_in[12 + 5] = 18; /* sectors per track */ |
xferp->data_in[q + 5] = d->sectors_per_track; |
812 |
|
|
813 |
/* 6,7 = data bytes per sector */ |
/* 6,7 = data bytes per sector */ |
814 |
xferp->data_in[12 + 6] = (d->logical_block_size >> 8) |
xferp->data_in[q + 6] = (d->logical_block_size >> 8) |
815 |
& 255; |
& 255; |
816 |
xferp->data_in[12 + 7] = d->logical_block_size & 255; |
xferp->data_in[q + 7] = d->logical_block_size & 255; |
817 |
|
|
818 |
xferp->data_in[12 + 8] = (d->ncyls >> 8) & 255; |
xferp->data_in[q + 8] = (d->ncyls >> 8) & 255; |
819 |
xferp->data_in[12 + 9] = d->ncyls & 255; |
xferp->data_in[q + 9] = d->ncyls & 255; |
820 |
|
|
821 |
xferp->data_in[12 + 28] = (d->rpms >> 8) & 255; |
xferp->data_in[q + 28] = (d->rpms >> 8) & 255; |
822 |
xferp->data_in[12 + 29] = d->rpms & 255; |
xferp->data_in[q + 29] = d->rpms & 255; |
823 |
break; |
break; |
824 |
default: |
default: |
825 |
fatal("[ MODE_SENSE for page %i is not yet " |
fatal("[ MODE_SENSE for page %i is not yet " |
865 |
ofs = d->tape_offset; |
ofs = d->tape_offset; |
866 |
|
|
867 |
fatal("[ READ tape, id=%i file=%i, cmd[1]=%02x size=%i" |
fatal("[ READ tape, id=%i file=%i, cmd[1]=%02x size=%i" |
868 |
", ofs=%lli ]\n", scsi_id, d->tape_filenr, |
", ofs=%lli ]\n", id, d->tape_filenr, |
869 |
xferp->cmd[1], (int)size, (long long)ofs); |
xferp->cmd[1], (int)size, (long long)ofs); |
870 |
} else { |
} else { |
871 |
if (xferp->cmd[0] == SCSICMD_READ) { |
if (xferp->cmd[0] == SCSICMD_READ) { |
897 |
* blocks to transfer. (NOTE: If the value is |
* blocks to transfer. (NOTE: If the value is |
898 |
* 0, this means 0, not 65536. :-) |
* 0, this means 0, not 65536. :-) |
899 |
*/ |
*/ |
900 |
ofs = (xferp->cmd[2] << 24) + (xferp->cmd[3] |
ofs = ((uint64_t)xferp->cmd[2] << 24) + |
901 |
<< 16) + (xferp->cmd[4] << 8) + |
(xferp->cmd[3] << 16) + (xferp->cmd[4] << 8) |
902 |
xferp->cmd[5]; |
+ xferp->cmd[5]; |
903 |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
904 |
} |
} |
905 |
|
|
928 |
* be set to NO SENSE".. |
* be set to NO SENSE".. |
929 |
*/ |
*/ |
930 |
if (d->is_a_tape && d->f != NULL && feof(d->f)) { |
if (d->is_a_tape && d->f != NULL && feof(d->f)) { |
931 |
debug(" feof id=%i\n", scsi_id); |
debug(" feof id=%i\n", id); |
932 |
xferp->status[0] = 0x02; /* CHECK CONDITION */ |
xferp->status[0] = 0x02; /* CHECK CONDITION */ |
933 |
|
|
934 |
d->filemark = 1; |
d->filemark = 1; |
937 |
xferp->data_in, size); |
xferp->data_in, size); |
938 |
|
|
939 |
if (d->is_a_tape && d->f != NULL) |
if (d->is_a_tape && d->f != NULL) |
940 |
d->tape_offset = ftell(d->f); |
d->tape_offset = ftello(d->f); |
941 |
|
|
942 |
/* TODO: other errors? */ |
/* TODO: other errors? */ |
943 |
break; |
break; |
975 |
* transfer. (NOTE: If the value is 0 this means 0, |
* transfer. (NOTE: If the value is 0 this means 0, |
976 |
* not 65536.) |
* not 65536.) |
977 |
*/ |
*/ |
978 |
ofs = (xferp->cmd[2] << 24) + (xferp->cmd[3] << 16) + |
ofs = ((uint64_t)xferp->cmd[2] << 24) + |
979 |
(xferp->cmd[4] << 8) + xferp->cmd[5]; |
(xferp->cmd[3] << 16) + (xferp->cmd[4] << 8) + |
980 |
|
xferp->cmd[5]; |
981 |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
retlen = (xferp->cmd[7] << 8) + xferp->cmd[8]; |
982 |
} |
} |
983 |
|
|
1025 |
if (xferp->cmd_len != 6) |
if (xferp->cmd_len != 6) |
1026 |
debug(" (weird len=%i)", xferp->cmd_len); |
debug(" (weird len=%i)", xferp->cmd_len); |
1027 |
|
|
1028 |
for (i=0; i<xferp->cmd_len ; i++) |
for (i=0; i<(ssize_t)xferp->cmd_len; i++) |
1029 |
debug(" %02x", xferp->cmd[i]); |
debug(" %02x", xferp->cmd[i]); |
1030 |
|
|
1031 |
/* TODO: actualy care about cmd[] */ |
/* TODO: actualy care about cmd[] */ |
1234 |
scsi_transfer_allocbuf(&xferp->data_in_len, |
scsi_transfer_allocbuf(&xferp->data_in_len, |
1235 |
&xferp->data_in, retlen, 1); |
&xferp->data_in, retlen, 1); |
1236 |
|
|
1237 |
/* TODO */ |
xferp->data_in[0] = 0; |
1238 |
|
xferp->data_in[1] = 10; |
1239 |
|
xferp->data_in[2] = 0; /* First track. */ |
1240 |
|
xferp->data_in[3] = 0; /* Last track. */ |
1241 |
|
|
1242 |
|
/* Track 0 data: */ |
1243 |
|
xferp->data_in[4] = 0x00; /* Reserved. */ |
1244 |
|
xferp->data_in[5] = 0x04; /* ADR + CTRL: |
1245 |
|
Data, not audio */ |
1246 |
|
xferp->data_in[6] = 0x00; /* Track nr */ |
1247 |
|
xferp->data_in[7] = 0x00; /* Reserved */ |
1248 |
|
/* 8..11 = absolute CDROM address */ |
1249 |
|
|
1250 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
1251 |
break; |
break; |
1286 |
} else { |
} else { |
1287 |
int i; |
int i; |
1288 |
fatal("[ unknown MODE_SELECT: cmd ="); |
fatal("[ unknown MODE_SELECT: cmd ="); |
1289 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<(ssize_t)xferp->cmd_len; i++) |
1290 |
fatal(" %02x", xferp->cmd[i]); |
fatal(" %02x", xferp->cmd[i]); |
1291 |
fatal(", data_out ="); |
fatal(", data_out ="); |
1292 |
for (i=0; i<xferp->data_out_len; i++) |
for (i=0; i<(ssize_t)xferp->data_out_len; i++) |
1293 |
fatal(" %02x", xferp->data_out[i]); |
fatal(" %02x", xferp->data_out[i]); |
1294 |
fatal(" ]"); |
fatal(" ]"); |
1295 |
} |
} |
1298 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
1299 |
break; |
break; |
1300 |
|
|
1301 |
case 0x1e: |
case SCSICMD_PREVENT_ALLOW_REMOVE: |
1302 |
debug("[ SCSI 0x%02x: TODO ]\n", xferp->cmd[0]); |
debug("[ SCSI 0x%02x Prevent/allow medium removal: " |
1303 |
|
"TODO ]\n", xferp->cmd[0]); |
|
/* TODO */ |
|
1304 |
|
|
1305 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
1306 |
break; |
break; |
1308 |
case 0xbd: |
case 0xbd: |
1309 |
fatal("[ SCSI 0x%02x (len %i), TODO: ", xferp->cmd[0], |
fatal("[ SCSI 0x%02x (len %i), TODO: ", xferp->cmd[0], |
1310 |
xferp->cmd_len); |
xferp->cmd_len); |
1311 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<(ssize_t)xferp->cmd_len; i++) |
1312 |
fatal(" %02x", xferp->cmd[i]); |
fatal(" %02x", xferp->cmd[i]); |
1313 |
fatal(" ]\n"); |
fatal(" ]\n"); |
1314 |
|
|
1332 |
&xferp->data_in, retlen, 1); |
&xferp->data_in, retlen, 1); |
1333 |
|
|
1334 |
diskimage__return_default_status_and_message(xferp); |
diskimage__return_default_status_and_message(xferp); |
1335 |
|
|
1336 |
break; |
break; |
1337 |
|
|
1338 |
default: |
default: |
1339 |
fatal("[ UNIMPLEMENTED SCSI command 0x%02x, disk id=%i ]\n", |
fatal("[ UNIMPLEMENTED SCSI command 0x%02x, disk id=%i ]\n", |
1340 |
xferp->cmd[0], scsi_id); |
xferp->cmd[0], id); |
1341 |
exit(1); |
exit(1); |
1342 |
} |
} |
1343 |
debug(" ]\n"); |
debug(" ]\n"); |
1353 |
* |
* |
1354 |
* Returns 1 if the access completed successfully, 0 otherwise. |
* Returns 1 if the access completed successfully, 0 otherwise. |
1355 |
*/ |
*/ |
1356 |
int diskimage_access(struct machine *machine, int scsi_id, int writeflag, |
int diskimage_access(struct machine *machine, int id, int type, int writeflag, |
1357 |
off_t offset, unsigned char *buf, size_t len) |
off_t offset, unsigned char *buf, size_t len) |
1358 |
{ |
{ |
1359 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1360 |
|
|
1361 |
while (d != NULL) { |
while (d != NULL) { |
1362 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
1363 |
break; |
break; |
1364 |
d = d->next; |
d = d->next; |
1365 |
} |
} |
1366 |
|
|
1367 |
if (d == NULL) { |
if (d == NULL) { |
1368 |
fatal("[ diskimage_access(): ERROR: trying to access a " |
fatal("[ diskimage_access(): ERROR: trying to access a " |
1369 |
"non-existant SCSI disk image (%i)\n", scsi_id); |
"non-existant %s disk image (id %i)\n", |
1370 |
|
diskimage_types[type], id); |
1371 |
return 0; |
return 0; |
1372 |
} |
} |
1373 |
|
|
1382 |
* The filename may be prefixed with one or more modifiers, followed |
* The filename may be prefixed with one or more modifiers, followed |
1383 |
* by a colon. |
* by a colon. |
1384 |
* |
* |
1385 |
* b specifies that this is the boot device |
* b specifies that this is a bootable device |
1386 |
* c CD-ROM (instead of normal SCSI DISK) |
* c CD-ROM (instead of a normal DISK) |
1387 |
* d SCSI DISK (this is the default) |
* d DISK (this is the default) |
1388 |
|
* f FLOPPY (instead of SCSI) |
1389 |
|
* gH;S; set geometry (H=heads, S=sectors per track, cylinders are |
1390 |
|
* automatically calculated). (This is ignored for floppies.) |
1391 |
* i IDE (instead of SCSI) |
* i IDE (instead of SCSI) |
1392 |
* r read-only (don't allow changes to the file) |
* r read-only (don't allow changes to the file) |
1393 |
* t SCSI tape |
* s SCSI (this is the default) |
1394 |
|
* t tape |
1395 |
* 0-7 force a specific SCSI ID number |
* 0-7 force a specific SCSI ID number |
1396 |
* |
* |
1397 |
* machine is assumed to be non-NULL. |
* machine is assumed to be non-NULL. |
1400 |
int diskimage_add(struct machine *machine, char *fname) |
int diskimage_add(struct machine *machine, char *fname) |
1401 |
{ |
{ |
1402 |
struct diskimage *d, *d2; |
struct diskimage *d, *d2; |
1403 |
int id = 0; |
int id = 0, override_heads=0, override_spt=0; |
1404 |
|
int64_t bytespercyl; |
1405 |
char *cp; |
char *cp; |
1406 |
int prefix_b = 0; |
int prefix_b=0, prefix_c=0, prefix_d=0, prefix_f=0, prefix_g=0; |
1407 |
int prefix_c = 0; |
int prefix_i=0, prefix_r=0, prefix_s=0, prefix_t=0, prefix_id = -1; |
|
int prefix_d = 0; |
|
|
int prefix_i = 0; |
|
|
int prefix_t = 0; |
|
|
int prefix_id = -1; |
|
|
int prefix_r = 0; |
|
1408 |
|
|
1409 |
if (fname == NULL) { |
if (fname == NULL) { |
1410 |
fprintf(stderr, "diskimage_add(): NULL ptr\n"); |
fprintf(stderr, "diskimage_add(): NULL ptr\n"); |
1436 |
case 'd': |
case 'd': |
1437 |
prefix_d = 1; |
prefix_d = 1; |
1438 |
break; |
break; |
1439 |
|
case 'f': |
1440 |
|
prefix_f = 1; |
1441 |
|
break; |
1442 |
|
case 'g': |
1443 |
|
prefix_g = 1; |
1444 |
|
override_heads = atoi(fname); |
1445 |
|
while (*fname != '\0' && *fname != ';') |
1446 |
|
fname ++; |
1447 |
|
if (*fname == ';') |
1448 |
|
fname ++; |
1449 |
|
override_spt = atoi(fname); |
1450 |
|
while (*fname != '\0' && *fname != ';' && |
1451 |
|
*fname != ':') |
1452 |
|
fname ++; |
1453 |
|
if (*fname == ';') |
1454 |
|
fname ++; |
1455 |
|
if (override_heads < 1 || |
1456 |
|
override_spt < 1) { |
1457 |
|
fatal("Bad geometry: heads=%i " |
1458 |
|
"spt=%i\n", override_heads, |
1459 |
|
override_spt); |
1460 |
|
exit(1); |
1461 |
|
} |
1462 |
|
break; |
1463 |
case 'i': |
case 'i': |
1464 |
prefix_i = 1; |
prefix_i = 1; |
1465 |
break; |
break; |
|
case 't': |
|
|
prefix_t = 1; |
|
|
break; |
|
1466 |
case 'r': |
case 'r': |
1467 |
prefix_r = 1; |
prefix_r = 1; |
1468 |
break; |
break; |
1469 |
|
case 's': |
1470 |
|
prefix_s = 1; |
1471 |
|
break; |
1472 |
|
case 't': |
1473 |
|
prefix_t = 1; |
1474 |
|
break; |
1475 |
case ':': |
case ':': |
1476 |
break; |
break; |
1477 |
default: |
default: |
1482 |
} |
} |
1483 |
} |
} |
1484 |
|
|
|
/* Calculate which ID to use: */ |
|
|
if (prefix_id == -1) { |
|
|
int free = 0, collision = 1; |
|
|
|
|
|
while (collision) { |
|
|
collision = 0; |
|
|
d = machine->first_diskimage; |
|
|
while (d != NULL) { |
|
|
if (d->id == free) { |
|
|
collision = 1; |
|
|
break; |
|
|
} |
|
|
d = d->next; |
|
|
} |
|
|
if (!collision) |
|
|
id = free; |
|
|
else |
|
|
free ++; |
|
|
} |
|
|
} else { |
|
|
id = prefix_id; |
|
|
|
|
|
d = machine->first_diskimage; |
|
|
while (d != NULL) { |
|
|
if (d->id == id) { |
|
|
fprintf(stderr, "disk image SCSI id %i " |
|
|
"already in use\n", id); |
|
|
exit(1); |
|
|
} |
|
|
d = d->next; |
|
|
} |
|
|
} |
|
|
|
|
1485 |
/* Allocate a new diskimage struct: */ |
/* Allocate a new diskimage struct: */ |
1486 |
d = malloc(sizeof(struct diskimage)); |
d = malloc(sizeof(struct diskimage)); |
1487 |
if (d == NULL) { |
if (d == NULL) { |
1499 |
d2->next = d; |
d2->next = d; |
1500 |
} |
} |
1501 |
|
|
1502 |
d->type = DISKIMAGE_SCSI; |
/* Default to IDE disks... */ |
1503 |
d->id = id; |
d->type = DISKIMAGE_IDE; |
1504 |
|
|
1505 |
|
/* ... but some machines use SCSI by default: */ |
1506 |
|
if (machine->machine_type == MACHINE_PMAX || |
1507 |
|
machine->machine_type == MACHINE_ARC) |
1508 |
|
d->type = DISKIMAGE_SCSI; |
1509 |
|
|
1510 |
|
if (prefix_i + prefix_f + prefix_s > 1) { |
1511 |
|
fprintf(stderr, "Invalid disk image prefix(es). You can" |
1512 |
|
"only use one of i, f, and s\nfor each disk image.\n"); |
1513 |
|
exit(1); |
1514 |
|
} |
1515 |
|
|
1516 |
if (prefix_i) |
if (prefix_i) |
1517 |
d->type = DISKIMAGE_IDE; |
d->type = DISKIMAGE_IDE; |
1518 |
|
if (prefix_f) |
1519 |
|
d->type = DISKIMAGE_FLOPPY; |
1520 |
|
if (prefix_s) |
1521 |
|
d->type = DISKIMAGE_SCSI; |
1522 |
|
|
1523 |
d->fname = strdup(fname); |
d->fname = strdup(fname); |
1524 |
if (d->fname == NULL) { |
if (d->fname == NULL) { |
1532 |
* Is this a tape, CD-ROM or a normal disk? |
* Is this a tape, CD-ROM or a normal disk? |
1533 |
* |
* |
1534 |
* An intelligent guess, if no prefixes are used, would be that |
* An intelligent guess, if no prefixes are used, would be that |
1535 |
* filenames ending with .iso are CD-ROM images. |
* filenames ending with .iso or .cdr are CD-ROM images. |
1536 |
*/ |
*/ |
1537 |
if (prefix_t) { |
if (prefix_t) { |
1538 |
d->is_a_tape = 1; |
d->is_a_tape = 1; |
1539 |
} else { |
} else { |
1540 |
if (prefix_c || |
if (prefix_c || |
1541 |
((strlen(d->fname) > 4 && |
((strlen(d->fname) > 4 && |
1542 |
strcasecmp(d->fname + strlen(d->fname) - 4, ".iso") == 0) |
(strcasecmp(d->fname + strlen(d->fname) - 4, ".cdr") == 0 || |
1543 |
|
strcasecmp(d->fname + strlen(d->fname) - 4, ".iso") == 0)) |
1544 |
&& !prefix_d) |
&& !prefix_d) |
1545 |
) { |
) { |
1546 |
d->is_a_cdrom = 1; |
d->is_a_cdrom = 1; |
1558 |
*/ |
*/ |
1559 |
|
|
1560 |
#if 0 |
#if 0 |
1561 |
if (machine->machine_type == MACHINE_DEC) |
if (machine->machine_type == MACHINE_PMAX) |
1562 |
d->logical_block_size = 512; |
d->logical_block_size = 512; |
1563 |
else |
else |
1564 |
d->logical_block_size = 2048; |
d->logical_block_size = 2048; |
1569 |
|
|
1570 |
diskimage_recalc_size(d); |
diskimage_recalc_size(d); |
1571 |
|
|
1572 |
|
if ((d->total_size == 720*1024 || d->total_size == 1474560 |
1573 |
|
|| d->total_size == 2949120 || d->total_size == 1228800) |
1574 |
|
&& !prefix_i && !prefix_s) |
1575 |
|
d->type = DISKIMAGE_FLOPPY; |
1576 |
|
|
1577 |
|
switch (d->type) { |
1578 |
|
case DISKIMAGE_FLOPPY: |
1579 |
|
if (d->total_size < 737280) { |
1580 |
|
fatal("\nTODO: small (non-80-cylinder) floppies?\n\n"); |
1581 |
|
exit(1); |
1582 |
|
} |
1583 |
|
d->cylinders = 80; |
1584 |
|
d->heads = 2; |
1585 |
|
d->sectors_per_track = d->total_size / (d->cylinders * |
1586 |
|
d->heads * 512); |
1587 |
|
break; |
1588 |
|
default:/* Non-floppies: */ |
1589 |
|
d->heads = 16; |
1590 |
|
d->sectors_per_track = 63; |
1591 |
|
if (prefix_g) { |
1592 |
|
d->chs_override = 1; |
1593 |
|
d->heads = override_heads; |
1594 |
|
d->sectors_per_track = override_spt; |
1595 |
|
} |
1596 |
|
bytespercyl = d->heads * d->sectors_per_track * 512; |
1597 |
|
d->cylinders = d->total_size / bytespercyl; |
1598 |
|
if (d->cylinders * bytespercyl < d->total_size) |
1599 |
|
d->cylinders ++; |
1600 |
|
} |
1601 |
|
|
1602 |
d->rpms = 3600; |
d->rpms = 3600; |
1603 |
|
|
1604 |
if (prefix_b) |
if (prefix_b) |
1615 |
exit(1); |
exit(1); |
1616 |
} |
} |
1617 |
|
|
1618 |
|
/* Calculate which ID to use: */ |
1619 |
|
if (prefix_id == -1) { |
1620 |
|
int free = 0, collision = 1; |
1621 |
|
|
1622 |
|
while (collision) { |
1623 |
|
collision = 0; |
1624 |
|
d2 = machine->first_diskimage; |
1625 |
|
while (d2 != NULL) { |
1626 |
|
/* (don't compare against ourselves :) */ |
1627 |
|
if (d2 == d) { |
1628 |
|
d2 = d2->next; |
1629 |
|
continue; |
1630 |
|
} |
1631 |
|
if (d2->id == free && d2->type == d->type) { |
1632 |
|
collision = 1; |
1633 |
|
break; |
1634 |
|
} |
1635 |
|
d2 = d2->next; |
1636 |
|
} |
1637 |
|
if (!collision) |
1638 |
|
id = free; |
1639 |
|
else |
1640 |
|
free ++; |
1641 |
|
} |
1642 |
|
} else { |
1643 |
|
id = prefix_id; |
1644 |
|
d2 = machine->first_diskimage; |
1645 |
|
while (d2 != NULL) { |
1646 |
|
/* (don't compare against ourselves :) */ |
1647 |
|
if (d2 == d) { |
1648 |
|
d2 = d2->next; |
1649 |
|
continue; |
1650 |
|
} |
1651 |
|
if (d2->id == id && d2->type == d->type) { |
1652 |
|
fprintf(stderr, "disk image id %i " |
1653 |
|
"already in use\n", id); |
1654 |
|
exit(1); |
1655 |
|
} |
1656 |
|
d2 = d2->next; |
1657 |
|
} |
1658 |
|
} |
1659 |
|
|
1660 |
|
d->id = id; |
1661 |
|
|
1662 |
return id; |
return id; |
1663 |
} |
} |
1664 |
|
|
1666 |
/* |
/* |
1667 |
* diskimage_bootdev(): |
* diskimage_bootdev(): |
1668 |
* |
* |
1669 |
* Returns the disk id (0..7) of the device which we're booting from. |
* Returns the disk id of the device which we're booting from. If typep is |
1670 |
|
* non-NULL, the type is returned as well. |
1671 |
* |
* |
1672 |
* If no disk was used as boot device, then -1 is returned. (In practice, |
* If no disk was used as boot device, then -1 is returned. (In practice, |
1673 |
* this is used to fake network (tftp) boot.) |
* this is used to fake network (tftp) boot.) |
1674 |
*/ |
*/ |
1675 |
int diskimage_bootdev(struct machine *machine) |
int diskimage_bootdev(struct machine *machine, int *typep) |
1676 |
{ |
{ |
1677 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d; |
1678 |
|
|
1679 |
|
d = machine->first_diskimage; |
1680 |
while (d != NULL) { |
while (d != NULL) { |
1681 |
if (d->is_boot_device) |
if (d->is_boot_device) { |
1682 |
|
if (typep != NULL) |
1683 |
|
*typep = d->type; |
1684 |
return d->id; |
return d->id; |
1685 |
|
} |
1686 |
d = d->next; |
d = d->next; |
1687 |
} |
} |
1688 |
|
|
1689 |
d = machine->first_diskimage; |
d = machine->first_diskimage; |
1690 |
if (d != NULL) |
if (d != NULL) { |
1691 |
|
if (typep != NULL) |
1692 |
|
*typep = d->type; |
1693 |
return d->id; |
return d->id; |
1694 |
|
} |
1695 |
|
|
1696 |
return -1; |
return -1; |
1697 |
} |
} |
1698 |
|
|
1699 |
|
|
1700 |
/* |
/* |
1701 |
|
* diskimage_getname(): |
1702 |
|
* |
1703 |
|
* Returns 1 if a valid disk image name was returned, 0 otherwise. |
1704 |
|
*/ |
1705 |
|
int diskimage_getname(struct machine *machine, int id, int type, |
1706 |
|
char *buf, size_t bufsize) |
1707 |
|
{ |
1708 |
|
struct diskimage *d = machine->first_diskimage; |
1709 |
|
|
1710 |
|
if (buf == NULL) |
1711 |
|
return 0; |
1712 |
|
|
1713 |
|
while (d != NULL) { |
1714 |
|
if (d->type == type && d->id == id) { |
1715 |
|
char *p = strrchr(d->fname, '/'); |
1716 |
|
if (p == NULL) |
1717 |
|
p = d->fname; |
1718 |
|
else |
1719 |
|
p ++; |
1720 |
|
snprintf(buf, bufsize, "%s", p); |
1721 |
|
return 1; |
1722 |
|
} |
1723 |
|
d = d->next; |
1724 |
|
} |
1725 |
|
return 0; |
1726 |
|
} |
1727 |
|
|
1728 |
|
|
1729 |
|
/* |
1730 |
* diskimage_is_a_cdrom(): |
* diskimage_is_a_cdrom(): |
1731 |
* |
* |
1732 |
* Returns 1 if a disk image is a SCSI CDROM, 0 otherwise. |
* Returns 1 if a disk image is a CDROM, 0 otherwise. |
1733 |
*/ |
*/ |
1734 |
int diskimage_is_a_cdrom(struct machine *machine, int scsi_id) |
int diskimage_is_a_cdrom(struct machine *machine, int id, int type) |
1735 |
{ |
{ |
1736 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1737 |
|
|
1738 |
while (d != NULL) { |
while (d != NULL) { |
1739 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
1740 |
return d->is_a_cdrom; |
return d->is_a_cdrom; |
1741 |
d = d->next; |
d = d->next; |
1742 |
} |
} |
1747 |
/* |
/* |
1748 |
* diskimage_is_a_tape(): |
* diskimage_is_a_tape(): |
1749 |
* |
* |
1750 |
* Returns 1 if a disk image is a SCSI tape, 0 otherwise. |
* Returns 1 if a disk image is a tape, 0 otherwise. |
1751 |
|
* |
1752 |
* (Used in src/machine.c, to select 'rz' vs 'tz' for DECstation |
* (Used in src/machine.c, to select 'rz' vs 'tz' for DECstation |
1753 |
* boot strings.) |
* boot strings.) |
1754 |
*/ |
*/ |
1755 |
int diskimage_is_a_tape(struct machine *machine, int scsi_id) |
int diskimage_is_a_tape(struct machine *machine, int id, int type) |
1756 |
{ |
{ |
1757 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1758 |
|
|
1759 |
while (d != NULL) { |
while (d != NULL) { |
1760 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
1761 |
return d->is_a_tape; |
return d->is_a_tape; |
1762 |
d = d->next; |
d = d->next; |
1763 |
} |
} |
1772 |
*/ |
*/ |
1773 |
void diskimage_dump_info(struct machine *machine) |
void diskimage_dump_info(struct machine *machine) |
1774 |
{ |
{ |
1775 |
int iadd=4; |
int iadd = DEBUG_INDENTATION; |
1776 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1777 |
|
|
1778 |
while (d != NULL) { |
while (d != NULL) { |
1786 |
case DISKIMAGE_IDE: |
case DISKIMAGE_IDE: |
1787 |
debug("IDE"); |
debug("IDE"); |
1788 |
break; |
break; |
1789 |
|
case DISKIMAGE_FLOPPY: |
1790 |
|
debug("FLOPPY"); |
1791 |
|
break; |
1792 |
default: |
default: |
1793 |
debug("UNKNOWN type %i", d->type); |
debug("UNKNOWN type %i", d->type); |
1794 |
} |
} |
1798 |
debug(" id %i, ", d->id); |
debug(" id %i, ", d->id); |
1799 |
debug("%s, ", d->writable? "read/write" : "read-only"); |
debug("%s, ", d->writable? "read/write" : "read-only"); |
1800 |
|
|
1801 |
debug("%lli MB (%lli sectors)%s\n", |
if (d->type == DISKIMAGE_FLOPPY) |
1802 |
(long long) (d->total_size / 1048576), |
debug("%lli KB", (long long) (d->total_size / 1024)); |
1803 |
(long long) (d->total_size / 512), |
else |
1804 |
d->is_boot_device? " (BOOT)" : ""); |
debug("%lli MB", (long long) (d->total_size / 1048576)); |
1805 |
|
|
1806 |
|
if (d->type == DISKIMAGE_FLOPPY || d->chs_override) |
1807 |
|
debug(" (CHS=%i,%i,%i)", d->cylinders, d->heads, |
1808 |
|
d->sectors_per_track); |
1809 |
|
else |
1810 |
|
debug(" (%lli sectors)", (long long) |
1811 |
|
(d->total_size / 512)); |
1812 |
|
|
1813 |
|
if (d->is_boot_device) |
1814 |
|
debug(" (BOOT)"); |
1815 |
|
debug("\n"); |
1816 |
|
|
1817 |
debug_indentation(-iadd); |
debug_indentation(-iadd); |
1818 |
|
|