1 |
|
/* |
2 |
|
* sys_amiga.cpp - System dependent routines, Amiga implementation |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-1999 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2001 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
24 |
|
#include <devices/trackdisk.h> |
25 |
|
#include <devices/scsidisk.h> |
26 |
|
#include <resources/disk.h> |
27 |
+ |
#define __USE_SYSBASE |
28 |
|
#include <proto/dos.h> |
29 |
|
#include <proto/exec.h> |
30 |
|
#include <proto/disk.h> |
31 |
+ |
#include <inline/dos.h> |
32 |
+ |
#include <inline/exec.h> |
33 |
+ |
#include <inline/disk.h> |
34 |
|
|
35 |
|
#include "sysdeps.h" |
36 |
|
#include "main.h" |
56 |
|
ULONG block_size; // Block size of device (must be a power of two) |
57 |
|
bool is_nsd; // New style device? |
58 |
|
bool does_64bit; // Supports 64 bit trackdisk commands? |
59 |
+ |
bool is_ejected; // Volume has been (logically) ejected |
60 |
+ |
bool is_2060scsi; // Enable workaround for 2060scsi.device CD-ROM TD_READ bug |
61 |
|
}; |
62 |
|
|
63 |
|
|
82 |
|
the_port = CreateMsgPort(); |
83 |
|
tmp_buf = (UBYTE *)AllocMem(TMP_BUF_SIZE, MEMF_CHIP | MEMF_PUBLIC); |
84 |
|
if (the_port == NULL || tmp_buf == NULL) { |
85 |
< |
ErrorAlert(GetString(STR_NO_MEM_ERR)); |
85 |
> |
ErrorAlert(STR_NO_MEM_ERR); |
86 |
|
QuitEmulator(); |
87 |
|
} |
88 |
|
} |
95 |
|
void SysExit(void) |
96 |
|
{ |
97 |
|
// Delete port and temporary buffer |
98 |
< |
if (the_port) |
98 |
> |
if (the_port) { |
99 |
|
DeleteMsgPort(the_port); |
100 |
< |
if (tmp_buf) |
100 |
> |
the_port = NULL; |
101 |
> |
} |
102 |
> |
if (tmp_buf) { |
103 |
|
FreeMem(tmp_buf, TMP_BUF_SIZE); |
104 |
+ |
tmp_buf = NULL; |
105 |
+ |
} |
106 |
|
} |
107 |
|
|
108 |
|
|
113 |
|
|
114 |
|
void SysAddFloppyPrefs(void) |
115 |
|
{ |
106 |
– |
#if 0 |
116 |
|
for (int i=0; i<4; i++) { |
117 |
|
ULONG id = GetUnitID(i); |
118 |
|
if (id == DRT_150RPM) { // We need an HD drive |
119 |
|
char str[256]; |
120 |
< |
sprintf(str, "/dev/mfm.device/%d/0/0/1474560/512", i); |
120 |
> |
sprintf(str, "/dev/mfm.device/%d/0/0/2880/512", i); |
121 |
|
PrefsAddString("floppy", str); |
122 |
|
} |
123 |
|
} |
115 |
– |
#endif |
124 |
|
} |
125 |
|
|
126 |
|
|
216 |
|
return NULL; |
217 |
|
|
218 |
|
// Open device |
219 |
< |
if (OpenDevice((UBYTE *)dev_name, dev_unit, (struct IORequest *)io, dev_flags)) { |
219 |
> |
if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)io, dev_flags)) { |
220 |
|
D(bug(" couldn't open device\n")); |
221 |
|
DeleteIORequest(io); |
222 |
|
return NULL; |
265 |
|
fh->block_size = dev_bsize; |
266 |
|
fh->is_nsd = is_nsd; |
267 |
|
fh->does_64bit = does_64bit; |
268 |
+ |
fh->is_ejected = false; |
269 |
+ |
fh->is_2060scsi = (strcmp(dev_name, "2060scsi.device") == 0); |
270 |
|
return fh; |
271 |
|
} |
272 |
|
} |
323 |
|
fh->io->io_Length = length; |
324 |
|
fh->io->io_Offset = offset; |
325 |
|
fh->io->io_Data = data; |
326 |
< |
if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != length) |
327 |
< |
return 0; |
328 |
< |
return fh->io->io_Actual; |
326 |
> |
|
327 |
> |
if (fh->is_2060scsi && fh->block_size == 2048) { |
328 |
> |
|
329 |
> |
// 2060scsi.device has serious problems reading CD-ROMs via TD_READ |
330 |
> |
static struct SCSICmd scsi; |
331 |
> |
const int SENSE_LENGTH = 256; |
332 |
> |
static UBYTE sense_buffer[SENSE_LENGTH]; // Buffer for autosense data |
333 |
> |
static UBYTE cmd_buffer[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
334 |
> |
|
335 |
> |
D(bug("send_io_request length=%lu offset=%lu\n", length, (ULONG) offset)); |
336 |
> |
|
337 |
> |
memset(sense_buffer, 0, sizeof(sense_buffer)); |
338 |
> |
|
339 |
> |
scsi.scsi_Command = cmd_buffer; |
340 |
> |
scsi.scsi_CmdLength = sizeof(cmd_buffer); |
341 |
> |
scsi.scsi_SenseData = sense_buffer; |
342 |
> |
scsi.scsi_SenseLength = SENSE_LENGTH; |
343 |
> |
scsi.scsi_Flags = SCSIF_AUTOSENSE | (writing ? SCSIF_WRITE : SCSIF_READ); |
344 |
> |
scsi.scsi_Data = (UWORD *) data; |
345 |
> |
scsi.scsi_Length = length; |
346 |
> |
|
347 |
> |
ULONG block_offset = (ULONG) offset / fh->block_size; |
348 |
> |
ULONG block_length = length / fh->block_size; |
349 |
> |
|
350 |
> |
cmd_buffer[2] = block_offset >> 24; |
351 |
> |
cmd_buffer[3] = block_offset >> 16; |
352 |
> |
cmd_buffer[4] = block_offset >> 8; |
353 |
> |
cmd_buffer[5] = block_offset & 0xff; |
354 |
> |
|
355 |
> |
cmd_buffer[7] = block_length >> 8; |
356 |
> |
cmd_buffer[8] = block_length & 0xff; |
357 |
> |
|
358 |
> |
fh->io->io_Command = HD_SCSICMD; |
359 |
> |
fh->io->io_Actual = 0; |
360 |
> |
fh->io->io_Offset = 0; |
361 |
> |
fh->io->io_Data = &scsi; |
362 |
> |
fh->io->io_Length = sizeof(scsi); |
363 |
> |
|
364 |
> |
BYTE result = DoIO((struct IORequest *)fh->io); |
365 |
> |
|
366 |
> |
if (result) { |
367 |
> |
D(bug("send_io_request SCSI FAIL result=%lu\n", result)); |
368 |
> |
|
369 |
> |
if (result == HFERR_BadStatus) { |
370 |
> |
D(bug("send_io_request SCSI Status=%lu\n", scsi.scsi_Status)); |
371 |
> |
if (scsi.scsi_Status == 2) { |
372 |
> |
D(bug("send_io_request Sense Key=%02lx\n", sense_buffer[2] & 0x0f)); |
373 |
> |
D(bug("send_io_request ASC=%02lx ASCQ=%02lx\n", sense_buffer[12], sense_buffer[13])); |
374 |
> |
} |
375 |
> |
} |
376 |
> |
return 0; |
377 |
> |
} |
378 |
> |
|
379 |
> |
D(bug("send_io_request SCSI Actual=%lu\n", scsi.scsi_Actual)); |
380 |
> |
|
381 |
> |
if (scsi.scsi_Actual != length) |
382 |
> |
return 0; |
383 |
> |
|
384 |
> |
return scsi.scsi_Actual; |
385 |
> |
|
386 |
> |
} else { |
387 |
> |
|
388 |
> |
// if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != length) |
389 |
> |
if (DoIO((struct IORequest *)fh->io)) |
390 |
> |
{ |
391 |
> |
D(bug("send_io_request/%ld: Actual=%lu length=%lu Err=%ld\n", __LINE__, fh->io->io_Actual, length, fh->io->io_Error)); |
392 |
> |
return 0; |
393 |
> |
} |
394 |
> |
return fh->io->io_Actual; |
395 |
> |
} |
396 |
|
} |
397 |
|
|
398 |
|
|
405 |
|
{ |
406 |
|
file_handle *fh = (file_handle *)arg; |
407 |
|
if (!fh) |
408 |
+ |
{ |
409 |
+ |
D(bug("Sys_read/%ld return 0\n", __LINE__)); |
410 |
|
return 0; |
411 |
+ |
} |
412 |
+ |
|
413 |
+ |
D(bug("Sys_read/%ld length=%ld\n", __LINE__, length)); |
414 |
|
|
415 |
|
// File or device? |
416 |
|
if (fh->is_file) { |
417 |
|
|
418 |
|
// File, seek to position |
419 |
|
if (Seek(fh->f, offset + fh->start_byte, OFFSET_BEGINNING) == -1) |
420 |
+ |
{ |
421 |
+ |
D(bug("Sys_read/%ld return 0\n", __LINE__)); |
422 |
|
return 0; |
423 |
+ |
} |
424 |
|
|
425 |
|
// Read data |
426 |
|
LONG actual = Read(fh->f, buffer, length); |
427 |
|
if (actual == -1) |
428 |
+ |
{ |
429 |
+ |
D(bug("Sys_read/%ld return 0\n", __LINE__)); |
430 |
|
return 0; |
431 |
+ |
} |
432 |
|
else |
433 |
+ |
{ |
434 |
+ |
D(bug("Sys_read/%ld return %ld\n", __LINE__, actual)); |
435 |
|
return actual; |
436 |
+ |
} |
437 |
|
|
438 |
|
} else { |
439 |
|
|
445 |
|
|
446 |
|
// Yes, read one block |
447 |
|
if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0) |
448 |
+ |
{ |
449 |
+ |
D(bug("Sys_read/%ld return %ld\n", __LINE__, 0)); |
450 |
|
return 0; |
451 |
+ |
} |
452 |
|
|
453 |
|
// Copy data to destination buffer |
454 |
|
size_t pre_length = fh->block_size - pre_offset; |
469 |
|
// Yes, read blocks |
470 |
|
size_t main_length = length & ~(fh->block_size - 1); |
471 |
|
if (send_io_request(fh, false, main_length, pos, buffer) == 0) |
472 |
+ |
{ |
473 |
+ |
D(bug("Sys_read/%ld return %ld\n", __LINE__, 0)); |
474 |
|
return 0; |
475 |
+ |
} |
476 |
|
|
477 |
|
// Adjust data pointers |
478 |
|
buffer = (uint8 *)buffer + main_length; |
486 |
|
|
487 |
|
// Yes, read one block |
488 |
|
if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0) |
489 |
+ |
{ |
490 |
+ |
D(bug("Sys_read/%ld return %ld\n", __LINE__, 0)); |
491 |
|
return 0; |
492 |
+ |
} |
493 |
|
|
494 |
|
// Copy data to destination buffer |
495 |
|
memcpy(buffer, tmp_buf, length); |
496 |
|
actual += length; |
497 |
|
} |
498 |
|
|
499 |
+ |
D(bug("Sys_read/%ld return %ld\n", __LINE__, actual)); |
500 |
|
return actual; |
501 |
|
} |
502 |
|
} |
511 |
|
{ |
512 |
|
file_handle *fh = (file_handle *)arg; |
513 |
|
if (!fh) |
514 |
+ |
{ |
515 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
516 |
|
return 0; |
517 |
+ |
} |
518 |
+ |
|
519 |
+ |
D(bug("Sys_write/%ld length=%ld\n", __LINE__, length)); |
520 |
|
|
521 |
|
// File or device? |
522 |
|
if (fh->is_file) { |
523 |
|
|
524 |
|
// File, seek to position if necessary |
525 |
|
if (Seek(fh->f, offset + fh->start_byte, OFFSET_BEGINNING) == -1) |
526 |
+ |
{ |
527 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
528 |
|
return 0; |
529 |
+ |
} |
530 |
|
|
531 |
|
// Write data |
532 |
|
LONG actual = Write(fh->f, buffer, length); |
533 |
|
if (actual == -1) |
534 |
+ |
{ |
535 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
536 |
|
return 0; |
537 |
+ |
} |
538 |
|
else |
539 |
+ |
{ |
540 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, actual)); |
541 |
|
return actual; |
542 |
+ |
} |
543 |
|
|
544 |
|
} else { |
545 |
|
|
551 |
|
|
552 |
|
// Yes, read one block |
553 |
|
if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0) |
554 |
+ |
{ |
555 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
556 |
|
return 0; |
557 |
+ |
} |
558 |
|
|
559 |
|
// Copy data from source buffer |
560 |
|
size_t pre_length = fh->block_size - pre_offset; |
564 |
|
|
565 |
|
// Write block back |
566 |
|
if (send_io_request(fh, true, fh->block_size, pos - pre_offset, tmp_buf) == 0) |
567 |
+ |
{ |
568 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
569 |
|
return 0; |
570 |
+ |
} |
571 |
|
|
572 |
|
// Adjust data pointers |
573 |
|
buffer = (uint8 *)buffer + pre_length; |
582 |
|
// Yes, write blocks |
583 |
|
size_t main_length = length & ~(fh->block_size - 1); |
584 |
|
if (send_io_request(fh, true, main_length, pos, buffer) == 0) |
585 |
+ |
{ |
586 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
587 |
|
return 0; |
588 |
+ |
} |
589 |
|
|
590 |
|
// Adjust data pointers |
591 |
|
buffer = (uint8 *)buffer + main_length; |
599 |
|
|
600 |
|
// Yes, read one block |
601 |
|
if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0) |
602 |
+ |
{ |
603 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
604 |
|
return 0; |
605 |
+ |
} |
606 |
|
|
607 |
|
// Copy data from source buffer |
608 |
|
memcpy(buffer, tmp_buf, length); |
609 |
|
|
610 |
|
// Write block back |
611 |
|
if (send_io_request(fh, true, fh->block_size, pos, tmp_buf) == 0) |
612 |
+ |
{ |
613 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, 0)); |
614 |
|
return 0; |
615 |
+ |
} |
616 |
|
actual += length; |
617 |
|
} |
618 |
|
|
619 |
+ |
D(bug("Sys_write/%ld return %ld\n", __LINE__, actual)); |
620 |
|
return actual; |
621 |
|
} |
622 |
|
} |
659 |
|
fh->io->io_Command = TD_EJECT; |
660 |
|
fh->io->io_Length = 1; |
661 |
|
DoIO((struct IORequest *)fh->io); |
662 |
+ |
|
663 |
+ |
fh->is_ejected = true; |
664 |
|
} |
665 |
|
} |
666 |
|
|
698 |
|
} else { |
699 |
|
|
700 |
|
// Device, check write protection |
568 |
– |
fh->io->io_Flags = IOF_QUICK; |
701 |
|
fh->io->io_Command = TD_PROTSTATUS; |
702 |
< |
BeginIO((struct IORequest *)fh->io); |
702 |
> |
DoIO((struct IORequest *)fh->io); |
703 |
|
if (fh->io->io_Actual) |
704 |
|
return true; |
705 |
|
else |
737 |
|
else { |
738 |
|
|
739 |
|
// Check medium status |
608 |
– |
fh->io->io_Flags = IOF_QUICK; |
740 |
|
fh->io->io_Command = TD_CHANGESTATE; |
741 |
|
fh->io->io_Actual = 0; |
742 |
< |
BeginIO((struct IORequest *)fh->io); |
743 |
< |
return fh->io->io_Actual == 0; |
742 |
> |
DoIO((struct IORequest *)fh->io); |
743 |
> |
bool inserted = (fh->io->io_Actual == 0); |
744 |
> |
|
745 |
> |
if (!inserted) { |
746 |
> |
// Disk was ejected and has now been taken out |
747 |
> |
fh->is_ejected = false; |
748 |
> |
} |
749 |
> |
|
750 |
> |
if (fh->is_ejected) { |
751 |
> |
// Disk was ejected but has not yet been taken out, report it as |
752 |
> |
// no longer in the drive |
753 |
> |
return false; |
754 |
> |
} else |
755 |
> |
return inserted; |
756 |
|
} |
757 |
|
} |
758 |
|
|