Logo Search packages:      
Sourcecode: cbmlink version File versions  Download package

int disk_write ( const struct comm comm,
unsigned  unit,
unsigned  interleave,
unsigned  track,
unsigned  track_end,
FILE *  file,
char *  buf 
)

copy a disk to the remote host

Parameters:
comm the communication primitives
unit the disk unit (drive 0 or 1)
interleave the interleave factor (number of sectors to skip)
track number of the track to start reading from
track_end number of the last track, plus 1
file output file
buf a buffer of at least 1260 bytes
Returns:
zero on success, nonzero on error

current sector, number of blocks, and block length

communication status

drive unit

buffer pointer reset command

position of the "track" display

interleave table

length of the input file

Definition at line 422 of file disk.c.

References backspaces, command_remote(), read_remote(), read_sector_file(), and write_remote().

Referenced by drive_image_write().

{
  /** current sector, number of blocks, and block length */
  unsigned sector = 0, blocks = 0, len;
  /** communication status */
  int status;
  /** drive unit */
  char drive = unit ? '1' : '0';
  /** buffer pointer reset command */
  static char bp[11];
  /** position of the "track" display */
  unsigned pos = 0;
  /** interleave table */
  char* iltab = buf + 260;
  /** length of the input file */
  unsigned maxblock = 0;

  if (interleave) {
#ifdef __BCC__
    maxblock = (unsigned long) (lseek (file->fd, 0L, SEEK_END) + 255) / 256;
#else /* __BCC__ */
    if (fseek (file, 0L, SEEK_END)) {
      perror ("disk_write: fseek");
      return -2;
    }
    maxblock = (unsigned) (ftell (file) + 255) / 256;
#endif /* __BCC__ */
  }

  buf += 3;
  memcpy (bp + 3, "B-P:2 0", 7);

  if ((status = command_remote (comm, buf, '1', drive, track, sector)) ||
      (status = read_remote (comm, 15, buf, &len)) || len < 3) {
  abort:
    if (status == -1)
      fputs ("\ndisk_write: communication failure\n", stderr);
    else
      fprintf (stderr, "\ndisk_write: remote status %d\n", status);
    return status;
  }
  if (memcmp (buf, "00,", 3)) {
  not00:
    fputs ("\ndisk_write: ", stderr);
    fwrite (buf, 1, len, stderr);
    fputc ('\n', stderr);
    return -2;
  }

  for (; track < track_end; track++) {
    if (pos)
      fputs (backspaces + (sizeof backspaces - 1) - pos, stderr);
    pos = fprintf (stderr, "track %u", track);
    fflush (stderr);

    if (interleave) {
      unsigned highsect = 1000, sectdone = 0;
      if (maxblock <= blocks)
      goto done;
      if (maxblock < blocks + highsect)
      highsect = maxblock - blocks;
      memset (iltab, 0, highsect);
      for (sector = 0; sectdone < highsect;
         sector += interleave + 1, sector %= highsect) {
      while (iltab[sector]) {
        if (++sector == highsect) {
        findnext:
          for (sector = 0; iltab[++sector]; );
          break;
        }
      }

#ifdef __BCC__
      {
        long ofs = 256L * (blocks + sector);
        if (lseek (file->fd, ofs, SEEK_SET) != ofs) {
          perror ("\ndisk_write: lseek");
          return 2;
        }
      }
#else /* __BCC__ */
      if (fseek (file, 256L * (blocks + sector), SEEK_SET)) {
        perror ("\ndisk_write: fseek");
        return -2;
      }
#endif /* __BCC__ */

      if (read_sector_file (file, sector, blocks + sectdone, buf))
        return 0;

      if ((status = write_remote (comm, 15, bp + 3, 7)) ||
          (status = write_remote (comm, 2, buf, 256)))
        goto abort;

      for (;;) {
        if ((status = command_remote (comm, buf, '2', drive,
                              track, sector)) ||
            (status = read_remote (comm, 15, buf, &len)) || len < 3)
          goto abort;
        if (!memcmp (buf, "66,", 3)) {
          /* illegal track or sector */
          if (!sector) {
            blocks += sectdone;
            goto done;
          }
          iltab[highsect = sector] = 2;
          if (sectdone < highsect)
            goto findnext;
          goto nexttrack;
        }
        else if (memcmp (buf, "00,", 3))
          goto not00;
        else
          break;
      }
      /* ok, mark the sector written */
      iltab[sector] = 1;
      sectdone++;
      }

    nexttrack:
      blocks += sectdone;
    }
    else {
      for (sector = 0; sector < 1000; sector++, blocks++) {
      if (read_sector_file (file, sector, blocks, buf))
        return 0;

      if ((status = write_remote (comm, 15, bp + 3, 7)) ||
          (status = write_remote (comm, 2, buf, 256)))
        goto abort;

      for (;;) {
        if ((status = command_remote (comm, buf, '2', drive,
                              track, sector)) ||
            (status = read_remote (comm, 15, buf, &len)) || len < 3)
          goto abort;
        if (!memcmp (buf, "66,", 3)) {
          /* illegal track or sector */
          if (!sector)
            goto done;
          goto trackdone;
        }
        else if (memcmp (buf, "00,", 3))
          goto not00;
        else
          break;
      }
      }
    trackdone:
      continue;
    }
  }

 done:
  fprintf (stderr, "\ndisk_write: %u blocks\n", blocks);
  return 0;
}


Generated by  Doxygen 1.6.0   Back to index