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.91 2005/05/27 07:29:24 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> |
56 |
extern int quiet_mode; |
extern int quiet_mode; |
57 |
extern int single_step; |
extern int single_step; |
58 |
|
|
59 |
|
static char *diskimage_types[] = DISKIMAGE_TYPES; |
60 |
|
|
61 |
static struct scsi_transfer *first_free_scsi_transfer_alloc = NULL; |
static struct scsi_transfer *first_free_scsi_transfer_alloc = NULL; |
62 |
|
|
208 |
/* |
/* |
209 |
* diskimage_exist(): |
* diskimage_exist(): |
210 |
* |
* |
211 |
* Returns 1 if the specified SCSI id exists, 0 otherwise. |
* Returns 1 if the specified disk id (for a specific type) exists, 0 |
212 |
|
* otherwise. |
213 |
*/ |
*/ |
214 |
int diskimage_exist(struct machine *machine, int scsi_id) |
int diskimage_exist(struct machine *machine, int id, int type) |
215 |
{ |
{ |
216 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
217 |
|
|
218 |
while (d != NULL) { |
while (d != NULL) { |
219 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
220 |
return 1; |
return 1; |
221 |
d = d->next; |
d = d->next; |
222 |
} |
} |
256 |
|
|
257 |
d->total_size = size; |
d->total_size = size; |
258 |
d->ncyls = d->total_size / 1048576; |
d->ncyls = d->total_size / 1048576; |
259 |
|
|
260 |
|
/* TODO: There is a mismatch between d->ncyls and d->cylinders, |
261 |
|
SCSI-based stuff usually doesn't care. TODO: Fix this. */ |
262 |
} |
} |
263 |
|
|
264 |
|
|
265 |
/* |
/* |
266 |
* diskimage_getsize(): |
* diskimage_getsize(): |
267 |
* |
* |
268 |
* Returns -1 if the specified SCSI id does not exists, otherwise |
* Returns -1 if the specified disk id/type does not exists, otherwise |
269 |
* the size of the disk image is returned. |
* the size of the disk image is returned. |
270 |
*/ |
*/ |
271 |
int64_t diskimage_getsize(struct machine *machine, int scsi_id) |
int64_t diskimage_getsize(struct machine *machine, int id, int type) |
272 |
{ |
{ |
273 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
274 |
|
|
275 |
while (d != NULL) { |
while (d != NULL) { |
276 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
277 |
return d->total_size; |
return d->total_size; |
278 |
d = d->next; |
d = d->next; |
279 |
} |
} |
282 |
|
|
283 |
|
|
284 |
/* |
/* |
285 |
|
* diskimage_getchs(): |
286 |
|
* |
287 |
|
* Returns the current CHS values of a disk image. |
288 |
|
*/ |
289 |
|
void diskimage_getchs(struct machine *machine, int id, int type, |
290 |
|
int *c, int *h, int *s) |
291 |
|
{ |
292 |
|
struct diskimage *d = machine->first_diskimage; |
293 |
|
|
294 |
|
while (d != NULL) { |
295 |
|
if (d->type == type && d->id == id) { |
296 |
|
*c = d->cylinders; |
297 |
|
*h = d->heads; |
298 |
|
*s = d->sectors_per_track; |
299 |
|
return; |
300 |
|
} |
301 |
|
d = d->next; |
302 |
|
} |
303 |
|
fatal("diskimage_getchs(): disk id %i (type %i) not found?\n", |
304 |
|
id, diskimage_types[type]); |
305 |
|
exit(1); |
306 |
|
} |
307 |
|
|
308 |
|
|
309 |
|
/* |
310 |
* diskimage__return_default_status_and_message(): |
* diskimage__return_default_status_and_message(): |
311 |
* |
* |
312 |
* Set the status and msg_in parts of a scsi_transfer struct |
* Set the status and msg_in parts of a scsi_transfer struct |
475 |
* 1 if otherwise ok, |
* 1 if otherwise ok, |
476 |
* 0 on error. |
* 0 on error. |
477 |
*/ |
*/ |
478 |
int diskimage_scsicommand(struct cpu *cpu, int scsi_id, |
int diskimage_scsicommand(struct cpu *cpu, int id, int type, |
479 |
struct scsi_transfer *xferp) |
struct scsi_transfer *xferp) |
480 |
{ |
{ |
481 |
int retlen, i; |
int retlen, i; |
492 |
|
|
493 |
d = machine->first_diskimage; |
d = machine->first_diskimage; |
494 |
while (d != NULL) { |
while (d != NULL) { |
495 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
496 |
break; |
break; |
497 |
d = d->next; |
d = d->next; |
498 |
} |
} |
499 |
if (d == NULL) { |
if (d == NULL) { |
500 |
fprintf(stderr, "[ diskimage_scsicommand(): SCSI disk" |
fprintf(stderr, "[ diskimage_scsicommand(): %s " |
501 |
" with id %i not connected? ]\n", scsi_id); |
" id %i not connected? ]\n", diskimage_types[type], id); |
502 |
} |
} |
503 |
|
|
504 |
if (xferp->cmd == NULL) { |
if (xferp->cmd == NULL) { |
513 |
} |
} |
514 |
|
|
515 |
debug("[ diskimage_scsicommand(id=%i) cmd=0x%02x: ", |
debug("[ diskimage_scsicommand(id=%i) cmd=0x%02x: ", |
516 |
scsi_id, xferp->cmd[0]); |
id, xferp->cmd[0]); |
517 |
|
|
518 |
#if 0 |
#if 0 |
519 |
fatal("[ diskimage_scsicommand(id=%i) cmd=0x%02x len=%i:", |
fatal("[ diskimage_scsicommand(id=%i) cmd=0x%02x len=%i:", |
520 |
scsi_id, xferp->cmd[0], xferp->cmd_len); |
id, xferp->cmd[0], xferp->cmd_len); |
521 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<xferp->cmd_len; i++) |
522 |
fatal(" %02x", xferp->cmd[i]); |
fatal(" %02x", xferp->cmd[i]); |
523 |
fatal("\n"); |
fatal("\n"); |
532 |
f = fopen("scsi_log.txt", "w"); |
f = fopen("scsi_log.txt", "w"); |
533 |
if (f != NULL) { |
if (f != NULL) { |
534 |
int i; |
int i; |
535 |
fprintf(f, "id=%i cmd =", scsi_id); |
fprintf(f, "id=%i cmd =", id); |
536 |
for (i=0; i<xferp->cmd_len; i++) |
for (i=0; i<xferp->cmd_len; i++) |
537 |
fprintf(f, " %02x", xferp->cmd[i]); |
fprintf(f, " %02x", xferp->cmd[i]); |
538 |
fprintf(f, "\n"); |
fprintf(f, "\n"); |
722 |
|
|
723 |
pagecode = xferp->cmd[2] & 0x3f; |
pagecode = xferp->cmd[2] & 0x3f; |
724 |
|
|
725 |
debug("[ MODE SENSE id %i, pagecode=%i ]\n", scsi_id, pagecode); |
debug("[ MODE SENSE id %i, pagecode=%i ]\n", id, pagecode); |
726 |
|
|
727 |
/* 4 bytes of header for 6-byte command, |
/* 4 bytes of header for 6-byte command, |
728 |
8 bytes of header for 10-byte command. */ |
8 bytes of header for 10-byte command. */ |
763 |
|
|
764 |
/* 10,11 = sectors per track */ |
/* 10,11 = sectors per track */ |
765 |
xferp->data_in[12 + 10] = 0; |
xferp->data_in[12 + 10] = 0; |
766 |
xferp->data_in[12 + 11] = 1; /* TODO */ |
xferp->data_in[12 + 11] = d->sectors_per_track; |
767 |
|
|
768 |
/* 12,13 = physical sector size */ |
/* 12,13 = physical sector size */ |
769 |
xferp->data_in[12 + 12] = |
xferp->data_in[12 + 12] = |
776 |
xferp->data_in[12 + 2] = (d->ncyls >> 16) & 255; |
xferp->data_in[12 + 2] = (d->ncyls >> 16) & 255; |
777 |
xferp->data_in[12 + 3] = (d->ncyls >> 8) & 255; |
xferp->data_in[12 + 3] = (d->ncyls >> 8) & 255; |
778 |
xferp->data_in[12 + 4] = d->ncyls & 255; |
xferp->data_in[12 + 4] = d->ncyls & 255; |
779 |
xferp->data_in[12 + 5] = 15; /* nr of heads */ |
xferp->data_in[12 + 5] = d->heads; |
780 |
|
|
781 |
xferp->data_in[12 + 20] = (d->rpms >> 8) & 255; |
xferp->data_in[12 + 20] = (d->rpms >> 8) & 255; |
782 |
xferp->data_in[12 + 21] = d->rpms & 255; |
xferp->data_in[12 + 21] = d->rpms & 255; |
789 |
xferp->data_in[12 + 2] = ((5000) >> 8) & 255; |
xferp->data_in[12 + 2] = ((5000) >> 8) & 255; |
790 |
xferp->data_in[12 + 3] = (5000) & 255; |
xferp->data_in[12 + 3] = (5000) & 255; |
791 |
|
|
792 |
xferp->data_in[12 + 4] = 2; /* nr of heads */ |
xferp->data_in[12 + 4] = d->heads; |
793 |
xferp->data_in[12 + 5] = 18; /* sectors per track */ |
xferp->data_in[12 + 5] = d->sectors_per_track; |
794 |
|
|
795 |
/* 6,7 = data bytes per sector */ |
/* 6,7 = data bytes per sector */ |
796 |
xferp->data_in[12 + 6] = (d->logical_block_size >> 8) |
xferp->data_in[12 + 6] = (d->logical_block_size >> 8) |
847 |
ofs = d->tape_offset; |
ofs = d->tape_offset; |
848 |
|
|
849 |
fatal("[ READ tape, id=%i file=%i, cmd[1]=%02x size=%i" |
fatal("[ READ tape, id=%i file=%i, cmd[1]=%02x size=%i" |
850 |
", ofs=%lli ]\n", scsi_id, d->tape_filenr, |
", ofs=%lli ]\n", id, d->tape_filenr, |
851 |
xferp->cmd[1], (int)size, (long long)ofs); |
xferp->cmd[1], (int)size, (long long)ofs); |
852 |
} else { |
} else { |
853 |
if (xferp->cmd[0] == SCSICMD_READ) { |
if (xferp->cmd[0] == SCSICMD_READ) { |
910 |
* be set to NO SENSE".. |
* be set to NO SENSE".. |
911 |
*/ |
*/ |
912 |
if (d->is_a_tape && d->f != NULL && feof(d->f)) { |
if (d->is_a_tape && d->f != NULL && feof(d->f)) { |
913 |
debug(" feof id=%i\n", scsi_id); |
debug(" feof id=%i\n", id); |
914 |
xferp->status[0] = 0x02; /* CHECK CONDITION */ |
xferp->status[0] = 0x02; /* CHECK CONDITION */ |
915 |
|
|
916 |
d->filemark = 1; |
d->filemark = 1; |
1307 |
|
|
1308 |
default: |
default: |
1309 |
fatal("[ UNIMPLEMENTED SCSI command 0x%02x, disk id=%i ]\n", |
fatal("[ UNIMPLEMENTED SCSI command 0x%02x, disk id=%i ]\n", |
1310 |
xferp->cmd[0], scsi_id); |
xferp->cmd[0], id); |
1311 |
exit(1); |
exit(1); |
1312 |
} |
} |
1313 |
debug(" ]\n"); |
debug(" ]\n"); |
1323 |
* |
* |
1324 |
* Returns 1 if the access completed successfully, 0 otherwise. |
* Returns 1 if the access completed successfully, 0 otherwise. |
1325 |
*/ |
*/ |
1326 |
int diskimage_access(struct machine *machine, int scsi_id, int writeflag, |
int diskimage_access(struct machine *machine, int id, int type, int writeflag, |
1327 |
off_t offset, unsigned char *buf, size_t len) |
off_t offset, unsigned char *buf, size_t len) |
1328 |
{ |
{ |
1329 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1330 |
|
|
1331 |
while (d != NULL) { |
while (d != NULL) { |
1332 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
1333 |
break; |
break; |
1334 |
d = d->next; |
d = d->next; |
1335 |
} |
} |
1336 |
|
|
1337 |
if (d == NULL) { |
if (d == NULL) { |
1338 |
fatal("[ diskimage_access(): ERROR: trying to access a " |
fatal("[ diskimage_access(): ERROR: trying to access a " |
1339 |
"non-existant SCSI disk image (%i)\n", scsi_id); |
"non-existant %s disk image (id %i)\n", |
1340 |
|
diskimage_types[type], id); |
1341 |
return 0; |
return 0; |
1342 |
} |
} |
1343 |
|
|
1352 |
* The filename may be prefixed with one or more modifiers, followed |
* The filename may be prefixed with one or more modifiers, followed |
1353 |
* by a colon. |
* by a colon. |
1354 |
* |
* |
1355 |
* b specifies that this is the boot device |
* b specifies that this is a bootable device |
1356 |
* c CD-ROM (instead of normal SCSI DISK) |
* c CD-ROM (instead of a normal DISK) |
1357 |
* d SCSI DISK (this is the default) |
* d DISK (this is the default) |
1358 |
|
* f FLOPPY (instead of SCSI) |
1359 |
|
* gH;S; set geometry (H=heads, S=sectors per track, cylinders are |
1360 |
|
* automatically calculated). (This is ignored for floppies.) |
1361 |
* i IDE (instead of SCSI) |
* i IDE (instead of SCSI) |
1362 |
* r read-only (don't allow changes to the file) |
* r read-only (don't allow changes to the file) |
1363 |
* t SCSI tape |
* s SCSI (this is the default) |
1364 |
|
* t tape |
1365 |
* 0-7 force a specific SCSI ID number |
* 0-7 force a specific SCSI ID number |
1366 |
* |
* |
1367 |
* machine is assumed to be non-NULL. |
* machine is assumed to be non-NULL. |
1370 |
int diskimage_add(struct machine *machine, char *fname) |
int diskimage_add(struct machine *machine, char *fname) |
1371 |
{ |
{ |
1372 |
struct diskimage *d, *d2; |
struct diskimage *d, *d2; |
1373 |
int id = 0; |
int id = 0, override_heads=0, override_spt=0; |
1374 |
|
int64_t bytespercyl; |
1375 |
char *cp; |
char *cp; |
1376 |
int prefix_b = 0; |
int prefix_b=0, prefix_c=0, prefix_d=0, prefix_f=0, prefix_g=0; |
1377 |
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; |
|
1378 |
|
|
1379 |
if (fname == NULL) { |
if (fname == NULL) { |
1380 |
fprintf(stderr, "diskimage_add(): NULL ptr\n"); |
fprintf(stderr, "diskimage_add(): NULL ptr\n"); |
1406 |
case 'd': |
case 'd': |
1407 |
prefix_d = 1; |
prefix_d = 1; |
1408 |
break; |
break; |
1409 |
|
case 'f': |
1410 |
|
prefix_f = 1; |
1411 |
|
break; |
1412 |
|
case 'g': |
1413 |
|
prefix_g = 1; |
1414 |
|
override_heads = atoi(fname); |
1415 |
|
while (*fname != '\0' && *fname != ';') |
1416 |
|
fname ++; |
1417 |
|
if (*fname == ';') |
1418 |
|
fname ++; |
1419 |
|
override_spt = atoi(fname); |
1420 |
|
while (*fname != '\0' && *fname != ';' && |
1421 |
|
*fname != ':') |
1422 |
|
fname ++; |
1423 |
|
if (*fname == ';') |
1424 |
|
fname ++; |
1425 |
|
if (override_heads < 1 || |
1426 |
|
override_spt < 1) { |
1427 |
|
fatal("Bad geometry: heads=%i " |
1428 |
|
"spt=%i\n", override_heads, |
1429 |
|
override_spt); |
1430 |
|
exit(1); |
1431 |
|
} |
1432 |
|
break; |
1433 |
case 'i': |
case 'i': |
1434 |
prefix_i = 1; |
prefix_i = 1; |
1435 |
break; |
break; |
|
case 't': |
|
|
prefix_t = 1; |
|
|
break; |
|
1436 |
case 'r': |
case 'r': |
1437 |
prefix_r = 1; |
prefix_r = 1; |
1438 |
break; |
break; |
1439 |
|
case 's': |
1440 |
|
prefix_s = 1; |
1441 |
|
break; |
1442 |
|
case 't': |
1443 |
|
prefix_t = 1; |
1444 |
|
break; |
1445 |
case ':': |
case ':': |
1446 |
break; |
break; |
1447 |
default: |
default: |
1452 |
} |
} |
1453 |
} |
} |
1454 |
|
|
|
/* 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; |
|
|
} |
|
|
} |
|
|
|
|
1455 |
/* Allocate a new diskimage struct: */ |
/* Allocate a new diskimage struct: */ |
1456 |
d = malloc(sizeof(struct diskimage)); |
d = malloc(sizeof(struct diskimage)); |
1457 |
if (d == NULL) { |
if (d == NULL) { |
1470 |
} |
} |
1471 |
|
|
1472 |
d->type = DISKIMAGE_SCSI; |
d->type = DISKIMAGE_SCSI; |
1473 |
d->id = id; |
|
1474 |
|
/* Special cases: some machines usually have FLOPPY/IDE, not SCSI: */ |
1475 |
|
if (machine->arch == ARCH_X86 || |
1476 |
|
machine->machine_type == MACHINE_COBALT || |
1477 |
|
machine->machine_type == MACHINE_HPCMIPS || |
1478 |
|
machine->machine_type == MACHINE_PS2) |
1479 |
|
d->type = DISKIMAGE_IDE; |
1480 |
|
|
1481 |
|
if (prefix_i + prefix_f + prefix_s > 1) { |
1482 |
|
fprintf(stderr, "Invalid disk image prefix(es). You can" |
1483 |
|
"only use one of i, f, and s\nfor each disk image.\n"); |
1484 |
|
exit(1); |
1485 |
|
} |
1486 |
|
|
1487 |
if (prefix_i) |
if (prefix_i) |
1488 |
d->type = DISKIMAGE_IDE; |
d->type = DISKIMAGE_IDE; |
1489 |
|
if (prefix_f) |
1490 |
|
d->type = DISKIMAGE_FLOPPY; |
1491 |
|
if (prefix_s) |
1492 |
|
d->type = DISKIMAGE_SCSI; |
1493 |
|
|
1494 |
d->fname = strdup(fname); |
d->fname = strdup(fname); |
1495 |
if (d->fname == NULL) { |
if (d->fname == NULL) { |
1539 |
|
|
1540 |
diskimage_recalc_size(d); |
diskimage_recalc_size(d); |
1541 |
|
|
1542 |
|
if ((d->total_size == 720*1024 || d->total_size == 1474560 |
1543 |
|
|| d->total_size == 2949120 || d->total_size == 1228800) |
1544 |
|
&& !prefix_i && !prefix_s) |
1545 |
|
d->type = DISKIMAGE_FLOPPY; |
1546 |
|
|
1547 |
|
switch (d->type) { |
1548 |
|
case DISKIMAGE_FLOPPY: |
1549 |
|
if (d->total_size < 737280) { |
1550 |
|
fatal("\nTODO: small (non-80-cylinder) floppies?\n\n"); |
1551 |
|
exit(1); |
1552 |
|
} |
1553 |
|
d->cylinders = 80; |
1554 |
|
d->heads = 2; |
1555 |
|
d->sectors_per_track = d->total_size / (d->cylinders * |
1556 |
|
d->heads * 512); |
1557 |
|
break; |
1558 |
|
default:/* Non-floppies: */ |
1559 |
|
d->heads = 16; |
1560 |
|
d->sectors_per_track = 63; |
1561 |
|
if (prefix_g) { |
1562 |
|
d->chs_override = 1; |
1563 |
|
d->heads = override_heads; |
1564 |
|
d->sectors_per_track = override_spt; |
1565 |
|
} |
1566 |
|
bytespercyl = d->heads * d->sectors_per_track * 512; |
1567 |
|
d->cylinders = d->total_size / bytespercyl; |
1568 |
|
if (d->cylinders * bytespercyl < d->total_size) |
1569 |
|
d->cylinders ++; |
1570 |
|
} |
1571 |
|
|
1572 |
d->rpms = 3600; |
d->rpms = 3600; |
1573 |
|
|
1574 |
if (prefix_b) |
if (prefix_b) |
1585 |
exit(1); |
exit(1); |
1586 |
} |
} |
1587 |
|
|
1588 |
|
/* Calculate which ID to use: */ |
1589 |
|
if (prefix_id == -1) { |
1590 |
|
int free = 0, collision = 1; |
1591 |
|
|
1592 |
|
while (collision) { |
1593 |
|
collision = 0; |
1594 |
|
d2 = machine->first_diskimage; |
1595 |
|
while (d2 != NULL) { |
1596 |
|
/* (don't compare against ourselves :) */ |
1597 |
|
if (d2 == d) { |
1598 |
|
d2 = d2->next; |
1599 |
|
continue; |
1600 |
|
} |
1601 |
|
if (d2->id == free && d2->type == d->type) { |
1602 |
|
collision = 1; |
1603 |
|
break; |
1604 |
|
} |
1605 |
|
d2 = d2->next; |
1606 |
|
} |
1607 |
|
if (!collision) |
1608 |
|
id = free; |
1609 |
|
else |
1610 |
|
free ++; |
1611 |
|
} |
1612 |
|
} else { |
1613 |
|
id = prefix_id; |
1614 |
|
d2 = machine->first_diskimage; |
1615 |
|
while (d2 != NULL) { |
1616 |
|
/* (don't compare against ourselves :) */ |
1617 |
|
if (d2 == d) { |
1618 |
|
d2 = d2->next; |
1619 |
|
continue; |
1620 |
|
} |
1621 |
|
if (d2->id == id && d2->type == d->type) { |
1622 |
|
fprintf(stderr, "disk image id %i " |
1623 |
|
"already in use\n", id); |
1624 |
|
exit(1); |
1625 |
|
} |
1626 |
|
d2 = d2->next; |
1627 |
|
} |
1628 |
|
} |
1629 |
|
|
1630 |
|
d->id = id; |
1631 |
|
|
1632 |
return id; |
return id; |
1633 |
} |
} |
1634 |
|
|
1636 |
/* |
/* |
1637 |
* diskimage_bootdev(): |
* diskimage_bootdev(): |
1638 |
* |
* |
1639 |
* 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 |
1640 |
|
* non-NULL, the type is returned as well. |
1641 |
* |
* |
1642 |
* 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, |
1643 |
* this is used to fake network (tftp) boot.) |
* this is used to fake network (tftp) boot.) |
1644 |
*/ |
*/ |
1645 |
int diskimage_bootdev(struct machine *machine) |
int diskimage_bootdev(struct machine *machine, int *typep) |
1646 |
{ |
{ |
1647 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d; |
1648 |
|
|
1649 |
|
d = machine->first_diskimage; |
1650 |
while (d != NULL) { |
while (d != NULL) { |
1651 |
if (d->is_boot_device) |
if (d->is_boot_device) { |
1652 |
|
if (typep != NULL) |
1653 |
|
*typep = d->type; |
1654 |
return d->id; |
return d->id; |
1655 |
|
} |
1656 |
d = d->next; |
d = d->next; |
1657 |
} |
} |
1658 |
|
|
1659 |
d = machine->first_diskimage; |
d = machine->first_diskimage; |
1660 |
if (d != NULL) |
if (d != NULL) { |
1661 |
|
if (typep != NULL) |
1662 |
|
*typep = d->type; |
1663 |
return d->id; |
return d->id; |
1664 |
|
} |
1665 |
|
|
1666 |
return -1; |
return -1; |
1667 |
} |
} |
1670 |
/* |
/* |
1671 |
* diskimage_is_a_cdrom(): |
* diskimage_is_a_cdrom(): |
1672 |
* |
* |
1673 |
* Returns 1 if a disk image is a SCSI CDROM, 0 otherwise. |
* Returns 1 if a disk image is a CDROM, 0 otherwise. |
1674 |
*/ |
*/ |
1675 |
int diskimage_is_a_cdrom(struct machine *machine, int scsi_id) |
int diskimage_is_a_cdrom(struct machine *machine, int id, int type) |
1676 |
{ |
{ |
1677 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1678 |
|
|
1679 |
while (d != NULL) { |
while (d != NULL) { |
1680 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
1681 |
return d->is_a_cdrom; |
return d->is_a_cdrom; |
1682 |
d = d->next; |
d = d->next; |
1683 |
} |
} |
1688 |
/* |
/* |
1689 |
* diskimage_is_a_tape(): |
* diskimage_is_a_tape(): |
1690 |
* |
* |
1691 |
* Returns 1 if a disk image is a SCSI tape, 0 otherwise. |
* Returns 1 if a disk image is a tape, 0 otherwise. |
1692 |
|
* |
1693 |
* (Used in src/machine.c, to select 'rz' vs 'tz' for DECstation |
* (Used in src/machine.c, to select 'rz' vs 'tz' for DECstation |
1694 |
* boot strings.) |
* boot strings.) |
1695 |
*/ |
*/ |
1696 |
int diskimage_is_a_tape(struct machine *machine, int scsi_id) |
int diskimage_is_a_tape(struct machine *machine, int id, int type) |
1697 |
{ |
{ |
1698 |
struct diskimage *d = machine->first_diskimage; |
struct diskimage *d = machine->first_diskimage; |
1699 |
|
|
1700 |
while (d != NULL) { |
while (d != NULL) { |
1701 |
if (d->type == DISKIMAGE_SCSI && d->id == scsi_id) |
if (d->type == type && d->id == id) |
1702 |
return d->is_a_tape; |
return d->is_a_tape; |
1703 |
d = d->next; |
d = d->next; |
1704 |
} |
} |
1727 |
case DISKIMAGE_IDE: |
case DISKIMAGE_IDE: |
1728 |
debug("IDE"); |
debug("IDE"); |
1729 |
break; |
break; |
1730 |
|
case DISKIMAGE_FLOPPY: |
1731 |
|
debug("FLOPPY"); |
1732 |
|
break; |
1733 |
default: |
default: |
1734 |
debug("UNKNOWN type %i", d->type); |
debug("UNKNOWN type %i", d->type); |
1735 |
} |
} |
1739 |
debug(" id %i, ", d->id); |
debug(" id %i, ", d->id); |
1740 |
debug("%s, ", d->writable? "read/write" : "read-only"); |
debug("%s, ", d->writable? "read/write" : "read-only"); |
1741 |
|
|
1742 |
debug("%lli MB (%lli sectors)%s\n", |
if (d->type == DISKIMAGE_FLOPPY) |
1743 |
(long long) (d->total_size / 1048576), |
debug("%lli KB", (long long) (d->total_size / 1024)); |
1744 |
(long long) (d->total_size / 512), |
else |
1745 |
d->is_boot_device? " (BOOT)" : ""); |
debug("%lli MB", (long long) (d->total_size / 1048576)); |
1746 |
|
|
1747 |
|
if (d->type == DISKIMAGE_FLOPPY || d->chs_override) |
1748 |
|
debug(" (CHS=%i,%i,%i)", d->cylinders, d->heads, |
1749 |
|
d->sectors_per_track); |
1750 |
|
else |
1751 |
|
debug(" (%lli sectors)", (long long) |
1752 |
|
(d->total_size / 512)); |
1753 |
|
|
1754 |
|
if (d->is_boot_device) |
1755 |
|
debug(" (BOOT)"); |
1756 |
|
debug("\n"); |
1757 |
|
|
1758 |
debug_indentation(-iadd); |
debug_indentation(-iadd); |
1759 |
|
|