ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/sys_amiga.cpp
(Generate patch)

Comparing BasiliskII/src/AmigaOS/sys_amiga.cpp (file contents):
Revision 1.1 by cebix, 1999-10-03T14:16:25Z vs.
Revision 1.5 by cebix, 2001-02-02T20:52:57Z

# Line 1 | Line 1
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
# Line 52 | Line 52 | struct file_handle {
52          ULONG block_size;               // Block size of device (must be a power of two)
53          bool is_nsd;                    // New style device?
54          bool does_64bit;                // Supports 64 bit trackdisk commands?
55 +        bool is_ejected;                // Volume has been (logically) ejected
56 +        bool is_2060scsi;               // Enable workaround for 2060scsi.device CD-ROM TD_READ bug
57   };
58  
59  
# Line 89 | Line 91 | void SysInit(void)
91   void SysExit(void)
92   {
93          // Delete port and temporary buffer
94 <        if (the_port)
94 >        if (the_port) {
95                  DeleteMsgPort(the_port);
96 <        if (tmp_buf)
96 >                the_port = NULL;
97 >        }
98 >        if (tmp_buf) {
99                  FreeMem(tmp_buf, TMP_BUF_SIZE);
100 +                tmp_buf = NULL;
101 +        }
102   }
103  
104  
# Line 103 | Line 109 | void SysExit(void)
109  
110   void SysAddFloppyPrefs(void)
111   {
106 #if 0
112          for (int i=0; i<4; i++) {
113                  ULONG id = GetUnitID(i);
114                  if (id == DRT_150RPM) { // We need an HD drive
115                          char str[256];
116 <                        sprintf(str, "/dev/mfm.device/%d/0/0/1474560/512", i);
116 >                        sprintf(str, "/dev/mfm.device/%d/0/0/2880/512", i);
117                          PrefsAddString("floppy", str);
118                  }
119          }
115 #endif
120   }
121  
122  
# Line 257 | Line 261 | void *Sys_open(const char *name, bool re
261                  fh->block_size = dev_bsize;
262                  fh->is_nsd = is_nsd;
263                  fh->does_64bit = does_64bit;
264 +                fh->is_ejected = false;
265 +                fh->is_2060scsi = (strcmp(dev_name, "2060scsi.device") == 0);
266                  return fh;
267          }
268   }
# Line 298 | Line 304 | void Sys_close(void *arg)
304  
305  
306   /*
307 + *  Send one I/O request, using 64-bit addressing if the device supports it
308 + */
309 +
310 + static loff_t send_io_request(file_handle *fh, bool writing, ULONG length, loff_t offset, APTR data)
311 + {
312 +        if (fh->does_64bit) {
313 +                fh->io->io_Command = writing ? NSCMD_TD_WRITE64 : NSCMD_TD_READ64;
314 +                fh->io->io_Actual = offset >> 32;
315 +        } else {
316 +                fh->io->io_Command = writing ? CMD_WRITE : CMD_READ;
317 +                fh->io->io_Actual = 0;
318 +        }
319 +        fh->io->io_Length = length;
320 +        fh->io->io_Offset = offset;
321 +        fh->io->io_Data = data;
322 +
323 +        if (fh->is_2060scsi && fh->block_size == 2048) {
324 +
325 +                // 2060scsi.device has serious problems reading CD-ROMs via TD_READ
326 +                static struct SCSICmd scsi;
327 +                const int SENSE_LENGTH = 256;
328 +                static UBYTE sense_buffer[SENSE_LENGTH];                // Buffer for autosense data
329 +                static UBYTE cmd_buffer[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
330 +
331 +                D(bug("send_io_request length=%lu  offset=%lu\n", length, (ULONG) offset));
332 +
333 +                memset(sense_buffer, 0, sizeof(sense_buffer));
334 +
335 +                scsi.scsi_Command = cmd_buffer;
336 +                scsi.scsi_CmdLength = sizeof(cmd_buffer);
337 +                scsi.scsi_SenseData = sense_buffer;
338 +                scsi.scsi_SenseLength = SENSE_LENGTH;
339 +                scsi.scsi_Flags = SCSIF_AUTOSENSE | (writing ? SCSIF_WRITE : SCSIF_READ);
340 +                scsi.scsi_Data = (UWORD  *) data;
341 +                scsi.scsi_Length = length;
342 +
343 +                ULONG block_offset = (ULONG) offset / fh->block_size;
344 +                ULONG block_length = length / fh->block_size;
345 +
346 +                cmd_buffer[2] = block_offset >> 24;
347 +                cmd_buffer[3] = block_offset >> 16;
348 +                cmd_buffer[4] = block_offset >> 8;
349 +                cmd_buffer[5] = block_offset & 0xff;
350 +
351 +                cmd_buffer[7] = block_length >> 8;
352 +                cmd_buffer[8] = block_length & 0xff;
353 +
354 +                fh->io->io_Command = HD_SCSICMD;
355 +                fh->io->io_Actual = 0;
356 +                fh->io->io_Offset = 0;
357 +                fh->io->io_Data = &scsi;
358 +                fh->io->io_Length = sizeof(scsi);
359 +
360 +                BYTE result = DoIO((struct IORequest *)fh->io);
361 +
362 +                if (result) {
363 +                        D(bug("send_io_request SCSI FAIL result=%lu\n", result));
364 +
365 +                        if (result == HFERR_BadStatus) {
366 +                                D(bug("send_io_request SCSI Status=%lu\n", scsi.scsi_Status));
367 +                                if (scsi.scsi_Status == 2) {
368 +                                        D(bug("send_io_request Sense Key=%02lx\n", sense_buffer[2] & 0x0f));
369 +                                        D(bug("send_io_request ASC=%02lx  ASCQ=%02lx\n", sense_buffer[12], sense_buffer[13]));
370 +                                }
371 +                        }
372 +                        return 0;
373 +                }
374 +
375 +                D(bug("send_io_request SCSI Actual=%lu\n", scsi.scsi_Actual));
376 +
377 +                if (scsi.scsi_Actual != length)
378 +                        return 0;
379 +
380 +                return scsi.scsi_Actual;
381 +
382 +        } else {
383 +
384 +                if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != length)
385 +                        return 0;
386 +                return fh->io->io_Actual;
387 +        }
388 + }
389 +
390 +
391 + /*
392   *  Read "length" bytes from file/device, starting at "offset", to "buffer",
393   *  returns number of bytes read (or 0)
394   */
# Line 324 | Line 415 | size_t Sys_read(void *arg, void *buffer,
415  
416          } else {
417  
418 <                // Device, pre-read (partial read of first block) neccessary?
418 >                // Device, pre-read (partial read of first block) necessary?
419                  loff_t pos = offset + fh->start_byte;
420                  size_t actual = 0;
421                  uint32 pre_offset = pos % fh->block_size;
422                  if (pre_offset) {
423  
424                          // Yes, read one block
425 <                        fh->io->io_Command = CMD_READ;
335 <                        fh->io->io_Length = fh->block_size;
336 <                        fh->io->io_Offset = pos - pre_offset;
337 <                        fh->io->io_Data = tmp_buf;
338 <                        if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != fh->block_size)
425 >                        if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0)
426                                  return 0;
427  
428                          // Copy data to destination buffer
# Line 356 | Line 443 | size_t Sys_read(void *arg, void *buffer,
443  
444                          // Yes, read blocks
445                          size_t main_length = length & ~(fh->block_size - 1);
446 <                        fh->io->io_Command = CMD_READ;
360 <                        fh->io->io_Length = main_length;
361 <                        fh->io->io_Offset = pos;
362 <                        fh->io->io_Data = buffer;
363 <                        if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != main_length)
446 >                        if (send_io_request(fh, false, main_length, pos, buffer) == 0)
447                                  return 0;
448  
449                          // Adjust data pointers
# Line 370 | Line 453 | size_t Sys_read(void *arg, void *buffer,
453                          actual += main_length;
454                  }
455  
456 <                // Post-read (partial read of last block) neccessary?
456 >                // Post-read (partial read of last block) necessary?
457                  if (length) {
458  
459                          // Yes, read one block
460 <                        fh->io->io_Command = CMD_READ;
378 <                        fh->io->io_Length = fh->block_size;
379 <                        fh->io->io_Offset = pos;
380 <                        fh->io->io_Data = tmp_buf;
381 <                        if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != fh->block_size)
460 >                        if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0)
461                                  return 0;
462  
463                          // Copy data to destination buffer
# Line 405 | Line 484 | size_t Sys_write(void *arg, void *buffer
484          // File or device?
485          if (fh->is_file) {
486  
487 <                // File, seek to position if neccessary
487 >                // File, seek to position if necessary
488                  if (Seek(fh->f, offset + fh->start_byte, OFFSET_BEGINNING) == -1)
489                          return 0;
490  
# Line 418 | Line 497 | size_t Sys_write(void *arg, void *buffer
497  
498          } else {
499  
500 <                // Device, write data
501 <                fh->io->io_Command = CMD_WRITE;
502 <                fh->io->io_Length = length;
503 <                fh->io->io_Offset = offset + fh->start_byte;
504 <                fh->io->io_Data = buffer;
505 <                if (DoIO((struct IORequest *)fh->io))
506 <                        return 0;
507 <                else
508 <                        return fh->io->io_Actual;
500 >                // Device, pre-write (partial write of first block) necessary
501 >                loff_t pos = offset + fh->start_byte;
502 >                size_t actual = 0;
503 >                uint32 pre_offset = pos % fh->block_size;
504 >                if (pre_offset) {
505 >
506 >                        // Yes, read one block
507 >                        if (send_io_request(fh, false, fh->block_size, pos - pre_offset, tmp_buf) == 0)
508 >                                return 0;
509 >
510 >                        // Copy data from source buffer
511 >                        size_t pre_length = fh->block_size - pre_offset;
512 >                        if (pre_length > length)
513 >                                pre_length = length;
514 >                        memcpy(tmp_buf + pre_offset, buffer, pre_length);
515 >
516 >                        // Write block back
517 >                        if (send_io_request(fh, true, fh->block_size, pos - pre_offset, tmp_buf) == 0)
518 >                                return 0;
519 >
520 >                        // Adjust data pointers
521 >                        buffer = (uint8 *)buffer + pre_length;
522 >                        pos += pre_length;
523 >                        length -= pre_length;
524 >                        actual += pre_length;
525 >                }
526 >
527 >                // Main write (complete writes of middle blocks) possible?
528 >                if (length >= fh->block_size) {
529 >
530 >                        // Yes, write blocks
531 >                        size_t main_length = length & ~(fh->block_size - 1);
532 >                        if (send_io_request(fh, true, main_length, pos, buffer) == 0)
533 >                                return 0;
534 >
535 >                        // Adjust data pointers
536 >                        buffer = (uint8 *)buffer + main_length;
537 >                        pos += main_length;
538 >                        length -= main_length;
539 >                        actual += main_length;
540 >                }
541 >
542 >                // Post-write (partial write of last block) necessary?
543 >                if (length) {
544 >
545 >                        // Yes, read one block
546 >                        if (send_io_request(fh, false, fh->block_size, pos, tmp_buf) == 0)
547 >                                return 0;
548 >
549 >                        // Copy data from source buffer
550 >                        memcpy(buffer, tmp_buf, length);
551 >
552 >                        // Write block back
553 >                        if (send_io_request(fh, true, fh->block_size, pos, tmp_buf) == 0)
554 >                                return 0;
555 >                        actual += length;
556 >                }
557 >
558 >                return actual;
559          }
560   }
561  
# Line 468 | Line 597 | void SysEject(void *arg)
597                  fh->io->io_Command = TD_EJECT;
598                  fh->io->io_Length = 1;
599                  DoIO((struct IORequest *)fh->io);
600 +
601 +                fh->is_ejected = true;
602          }
603   }
604  
# Line 505 | Line 636 | bool SysIsReadOnly(void *arg)
636          } else {
637  
638                  // Device, check write protection
508                fh->io->io_Flags = IOF_QUICK;
639                  fh->io->io_Command = TD_PROTSTATUS;
640 <                BeginIO((struct IORequest *)fh->io);
640 >                DoIO((struct IORequest *)fh->io);
641                  if (fh->io->io_Actual)
642                          return true;
643                  else
# Line 545 | Line 675 | bool SysIsDiskInserted(void *arg)
675          else {
676  
677                  // Check medium status
548                fh->io->io_Flags = IOF_QUICK;
678                  fh->io->io_Command = TD_CHANGESTATE;
679                  fh->io->io_Actual = 0;
680 <                BeginIO((struct IORequest *)fh->io);
681 <                return fh->io->io_Actual == 0;
680 >                DoIO((struct IORequest *)fh->io);
681 >                bool inserted = (fh->io->io_Actual == 0);
682 >
683 >                if (!inserted) {
684 >                        // Disk was ejected and has now been taken out
685 >                        fh->is_ejected = false;
686 >                }
687 >
688 >                if (fh->is_ejected) {
689 >                        // Disk was ejected but has not yet been taken out, report it as
690 >                        // no longer in the drive
691 >                        return false;
692 >                } else
693 >                        return inserted;
694          }
695   }
696  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines