Esempio n. 1
0
// Find the number of cylinders the disk has. We step down the disk until we
// find unreadable tracks, the cylinder number in header doesn't match, or
// seek times out. Various disks have different behavior. The tracks past the end
// leading to the park zone are normally not formated. Many drives won't let you
// seek past the last cylinder. They either return to track zero or perform a
// recalibrate which may take enough time for the seek to timeout. Really old
// disk will just hit the end stop so can get the same cylinder. Hitting end stop
// probably isn't great.
//
// drive_params: Drive parameters determined so far and return what we have determined
// start_cyl: cylinder head is on at entry
// head: head currently selected
// deltas: MFM delta time transition data to analyze (filled after read)
//
// TODO, this won't deal well with spared cylinders when they have nonsequential
// values
static void analyze_disk_size(DRIVE_PARAMS *drive_params, int start_cyl,
      int head, void *deltas, int max_deltas) {
   int msg_mask_hold;
   int max_cyl;
   int not_next_cyl, not_next_cyl_count;
   int any_header_found;
   int no_header_count;
   SECTOR_STATUS sector_status_list[MAX_SECTORS];
   int cyl;
   int i;
   int last_printed_cyl;

   max_cyl = 0;
   no_header_count = 0;
   not_next_cyl_count = 0;

   for (cyl = start_cyl + 1; cyl < MAX_CYL; cyl++) {
      if (cyl % 5 == 0)
         msg(MSG_PROGRESS, "At cyl %d\r", cyl);

      if (drive_step(drive_params->step_speed, 1, 
           DRIVE_STEP_UPDATE_CYL, DRIVE_STEP_RET_ERR) != 0) {
         msg(MSG_INFO, "Max cylinder set from drive timeout on seek\n");
         break;
      }
      drive_read_track(drive_params, cyl, head, deltas, max_deltas);

      mfm_init_sector_status_list(sector_status_list, drive_params->num_sectors);
      msg_mask_hold = msg_set_err_mask(decode_errors);
      mfm_decode_track(drive_params, cyl, head, deltas, NULL, sector_status_list);
      msg_set_err_mask(msg_mask_hold);
      any_header_found = 0;
      not_next_cyl = 0;
      last_printed_cyl = -1;
      for (i = 0; i < drive_params->num_sectors; i++) {
         if (sector_status_list[i].status & SECT_HEADER_FOUND) {
            any_header_found = 1;
            max_cyl = MAX(max_cyl, sector_status_list[i].cyl);
            if (cyl != sector_status_list[i].cyl && last_printed_cyl != cyl) {
               msg(MSG_INFO, "Found cylinder %d expected %d\n",sector_status_list[i].cyl, cyl);
               last_printed_cyl = cyl;
               not_next_cyl = 1;
            }
         }
      }
      if (!any_header_found) {
         if (++no_header_count >= 2) {
            msg(MSG_INFO, "Stopping end of disk search due to two unreadable tracks in a row\n");
            break;
         } else {
            msg(MSG_INFO, "No sectors readable from cylinder %d\n",cyl);
         }
      } else {
         no_header_count = 0;
      }
      if (not_next_cyl) {
         if (++not_next_cyl_count >= 2) {
            msg(MSG_INFO, "Stopping end of disk search due to mismatching cylinder count\n");
            break;
         }
      } else {
         not_next_cyl_count = 0;
      }
   }
   drive_params->num_cyl = max_cyl + 1;
   msg(MSG_INFO, "Number of cylinders %d, %.1f MB\n", drive_params->num_cyl,
         (double) drive_params->num_cyl * drive_params->num_head *
         drive_params->num_sectors * drive_params->sector_size / (1000.0*1000));
   // We don't know where head is so return to 0
   drive_seek_track0();
}
Esempio n. 2
0
static void process_cmd( wd1793_t *device )
{
    unsigned char cmd = device->command;

    if ( (cmd & 0x80) == 0 )
    {
        // type I command
        device->status = STAT_BUSY;
        device->out_status &= ~(WD1793_DRQ | WD1793_INTRQ);

        if ( FLAG_H(cmd) )
            device->out_status |= WD1793_HLD;
        else
            device->out_status &= ~WD1793_HLD;

        if ( (cmd & 0xE0) == 0 )
        {
            // seek and restore commands
            if ( (cmd & 0x10) == 0 )
            {
                // restore command
                device->track = 0xFF;
                device->data = 0;
            }

            device->dsr = device->data;

            while ( device->dsr != device->track )
            {
                if ( device->dsr > device->track )
                {
                    device->out_status |= WD1793_DIR;
                    device->track ++;
                }
                else
                {
                    device->out_status &= ~WD1793_DIR;
                    device->track --;
                }

                drive_step( device );
            }
        }
        else
        {
            // step commands
            if ( (cmd & 0x60) == 4 )        // step in
                device->out_status |= WD1793_DIR;
            else if ( (cmd & 0x60) == 6 )   // step out
                device->out_status &= ~WD1793_DIR;

            if ( FLAG_U(cmd) )
            {
                if ( device->out_status & WD1793_DIR )
                    device->track ++;
                else
                    device->track --;
            }

            drive_step( device );
        }


        /*if ( !(device->out_status & WD1793_DIR) && (device->disk.track == 0) )
        {
            device->track = 0;
            device->count = 1;  // no delay
        }
        else
        {
            drive_step( device );
            device->count = pos_delays[FLAG_R(cmd)];
        }*/

        device->state = WD1793_TYPE1;

        // HACK
        device->status &= ~(STAT_BUSY | STAT_TRACK_0);
        if ( device->disk.track == 0 )
        {
            device->status |= STAT_TRACK_0;
            device->track = 0;
        }
        device->out_status |= WD1793_INTRQ;
    }
    else if ( (cmd & 0x40) == 0 )
    {
        // type II command
        device->status |= STAT_BUSY;
    }
    else if ( (cmd & 0x30) == 0x01 )
    {
        // type IV command
        device->status &= ~STAT_BUSY;
    }
    else
    {
        // type III command
        device->status |= STAT_BUSY;
    }
}