Exemplo n.º 1
0
/*
    Perform seek command

    unit: floppy drive index
    cylinder: track to seek for
    head: head for which the seek is performed

    Return FALSE if the seek was successful
*/
static int fd800_do_seek(int unit, int cylinder, int head)
{
	int retries;

	if (cylinder > 76)
	{
		fd800.stat_reg |= status_invalid_cmd;
		return TRUE;
	}

	if (!fd800.drv[unit].img->exists())
	{
		fd800.stat_reg |= status_drv_not_ready;	/* right??? */
		return TRUE;
	}

	if (fd800.drv[unit].log_cylinder[head] == -1)
	{	/* current track ID is unknown: read it */
		if (!fd800_read_id(unit, head, &fd800.drv[unit].log_cylinder[head], NULL))
		{
			fd800.stat_reg |= status_ID_not_found;
			return TRUE;
		}
	}
	/* exit if we are already at the requested track */
	if (fd800.drv[unit].log_cylinder[head] == cylinder)
	{
		/*fd800.stat_reg |= status_OP_complete;*/
		return FALSE;
	}
	for (retries=0; retries<10; retries++)
	{	/* seek to requested track */
		floppy_drive_seek(&fd800.drv[unit].img->device(), cylinder-fd800.drv[unit].log_cylinder[head]);
		/* update physical track position */
		if (fd800.drv[unit].phys_cylinder != -1)
			fd800.drv[unit].phys_cylinder += cylinder-fd800.drv[unit].log_cylinder[head];
		/* read new track ID */
		if (!fd800_read_id(unit, head, &fd800.drv[unit].log_cylinder[head], NULL))
		{
			fd800.drv[unit].log_cylinder[head] = -1;
			fd800.stat_reg |= status_ID_not_found;
			return TRUE;
		}
		/* exit if we have reached the requested track */
		if (fd800.drv[unit].log_cylinder[head] == cylinder)
		{
			/*fd800.stat_reg |= status_OP_complete;*/
			return FALSE;
		}
	}
	/* track not found */
	fd800.stat_reg |= status_seek_err;
	return TRUE;
}
Exemplo n.º 2
0
/* Seek bottom half */
static void mc6843_finish_SEK( device_t *device )
{
	mc6843_t* mc6843 = get_safe_token( device );
	device_t* img = mc6843_floppy_image( device );

	/* seek to track */
	floppy_drive_seek( img, mc6843->GCR - mc6843->CTAR );

	LOG(( "%f mc6843_finish_SEK: from %i to %i (actual=%i)\n", device->machine().time().as_double(), mc6843->CTAR, mc6843->GCR, floppy_drive_get_current_track( img ) ));

	/* update state */
	mc6843->CTAR = mc6843->GCR;
	mc6843->SAR = 0;
	mc6843_cmd_end( device );
}
Exemplo n.º 3
0
/* Seek Track Zero bottom half */
static void mc6843_finish_STZ( device_t *device )
{
	mc6843_t* mc6843 = get_safe_token( device );
	device_t* img = mc6843_floppy_image( device );
	int i;

	/* seek to track zero */
	for ( i=0; i<83; i++ )
	{
		if (floppy_tk00_r(img) == CLEAR_LINE)
			break;
		floppy_drive_seek( img, -1 );
	}

	LOG(( "%f mc6843_finish_STZ: actual=%i\n", device->machine().time().as_double(), floppy_drive_get_current_track( img ) ));

	/* update state */
	mc6843->CTAR = 0;
	mc6843->GCR = 0;
	mc6843->SAR = 0;
	mc6843->STRB |= floppy_tk00_r(img) << 4;

	mc6843_cmd_end( device );
}
Exemplo n.º 4
0
static void i8271_command_execute(device_t *device)
{
	i8271_t *i8271 = get_safe_token(device);
	device_t *img = current_image(device);

	/* clear it = good completion status */
	/* this will be changed if anything bad happens! */
	i8271->ResultRegister = 0;

	switch (i8271->Command)
	{
		case I8271_COMMAND_SPECIFY:
		{
			switch (i8271->CommandParameters[0])
			{
				case 0x0d:
				{
					LOG(("Initialization\n"));
					i8271->StepRate = i8271->CommandParameters[1];
					i8271->HeadSettlingTime = i8271->CommandParameters[2];
					i8271->IndexCountBeforeHeadUnload = (i8271->CommandParameters[3]>>4) & 0x0f;
					i8271->HeadLoadTime = (i8271->CommandParameters[3] & 0x0f);
				}
				break;

				case 0x010:
				{
					LOG(("Load bad Tracks Surface 0\n"));
					i8271_load_bad_tracks(device,0);

				}
				break;

				case 0x018:
				{
					LOG(("Load bad Tracks Surface 1\n"));
					i8271_load_bad_tracks(device,1);

				}
				break;
			}

			/* no result */
			i8271_command_complete(device,0,0);
		}
		break;

		case I8271_COMMAND_READ_SPECIAL_REGISTER:
		{
			/* unknown - what is read when a special register that isn't allowed is specified? */
			int data = 0x0ff;

			switch (i8271->CommandParameters[0])
			{
				case I8271_SPECIAL_REGISTER_MODE_REGISTER:
				{
					data = i8271->Mode;
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_0_CURRENT_TRACK:
				{
					data = i8271_read_current_track(device, 0);

				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_1_CURRENT_TRACK:
				{
					data = i8271_read_current_track(device, 1);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_1:
				{
					data = i8271_read_bad_track(device, 0,1);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_2:
				{
					data = i8271_read_bad_track(device, 0,2);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_1:
				{
					data = i8271_read_bad_track(device, 1,1);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_2:
				{
					data = i8271_read_bad_track(device, 1,2);
				}
				break;

				case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_OUTPUT_PORT:
				{
					FDC_LOG_COMMAND("Read Drive Control Output port\n");

					i8271_get_drive(device);

					/* assumption: select bits reflect the select bits from the previous
                    command. i.e. read drive status */
					data = (i8271->drive_control_output & ~0x0c0)
						| (i8271->CommandRegister & 0x0c0);


				}
				break;

				case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_INPUT_PORT:
				{
					/* bit 7: not used */
					/* bit 6: ready 1 */
					/* bit 5: write fault */
					/* bit 4: index */
					/* bit 3: wr prot */
					/* bit 2: rdy 0 */
					/* bit 1: track 0 */
					/* bit 0: cnt/opi */

					FDC_LOG_COMMAND("Read Drive Control Input port\n");


					i8271->drive_control_input = (1<<6) | (1<<2);

					/* bit 3 = 0 if write protected */
					i8271->drive_control_input |= floppy_wpt_r(img) << 3;

					/* bit 1 = 0 if head at track 0 */
					i8271->drive_control_input |= floppy_tk00_r(img) << 1;

					/* need to setup this register based on drive selected */
					data = i8271->drive_control_input;
				}
				break;

			}

			i8271->ResultRegister = data;

			i8271_command_complete(device,1,0);
		}
		break;


		case I8271_COMMAND_WRITE_SPECIAL_REGISTER:
		{
			switch (i8271->CommandParameters[0])
			{
				case I8271_SPECIAL_REGISTER_MODE_REGISTER:
				{
					/* TODO: Check bits 6-7 and 5-2 are valid */
					i8271->Mode = i8271->CommandParameters[1];

					if (i8271->Mode & 0x01)
					{
						LOG(("Mode: Non-DMA\n"));
					}
					else
					{
						LOG(("Mode: DMA\n"));
					}

					if (i8271->Mode & 0x02)
					{
						LOG(("Single actuator\n"));
					}
					else
					{
						LOG(("Double actuator\n"));
					}
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_0_CURRENT_TRACK:
				{
					LOG(("Surface 0 Current Track\n"));
					i8271_write_current_track(device, 0, i8271->CommandParameters[1]);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_1_CURRENT_TRACK:
				{
					LOG(("Surface 1 Current Track\n"));
					i8271_write_current_track(device, 1, i8271->CommandParameters[1]);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_1:
				{
					LOG(("Surface 0 Bad Track 1\n"));
					i8271_write_bad_track(device, 0, 1, i8271->CommandParameters[1]);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_0_BAD_TRACK_2:
				{
					LOG(("Surface 0 Bad Track 2\n"));
					i8271_write_bad_track(device, 0, 2,i8271->CommandParameters[1]);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_1:
				{
					LOG(("Surface 1 Bad Track 1\n"));


					i8271_write_bad_track(device, 1, 1, i8271->CommandParameters[1]);
				}
				break;

				case I8271_SPECIAL_REGISTER_SURFACE_1_BAD_TRACK_2:
				{
					LOG(("Surface 1 Bad Track 2\n"));

					i8271_write_bad_track(device, 1, 2, i8271->CommandParameters[1]);
				}
				break;

				case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_OUTPUT_PORT:
				{
//                  /* get drive selected */
//                  i8271->drive = (i8271->CommandParameters[1]>>6) & 0x03;

					FDC_LOG_COMMAND("Write Drive Control Output port\n");


					if (i8271->CommandParameters[1] & 0x01)
					{
						LOG(("Write Enable\n"));
					}
					if (i8271->CommandParameters[1] & 0x02)
					{
						LOG(("Seek/Step\n"));
					}
					if (i8271->CommandParameters[1] & 0x04)
					{
						LOG(("Direction\n"));
					}
					if (i8271->CommandParameters[1] & 0x08)
					{
						LOG(("Load Head\n"));
					}
					if (i8271->CommandParameters[1] & 0x010)
					{
						LOG(("Low head current\n"));
					}
					if (i8271->CommandParameters[1] & 0x020)
					{
						LOG(("Write Fault Reset\n"));
					}

					LOG(("Select %02x\n", (i8271->CommandParameters[1] & 0x0c0)>>6));

					/* get drive */
					i8271_get_drive(device);

					/* on bbc dfs 09 this is the side select output */
					i8271->side = (i8271->CommandParameters[1]>>5) & 0x01;

					/* load head - on mini-sized drives this turns on the disc motor,
                    on standard-sized drives this loads the head and turns the motor on */
					floppy_mon_w(img, !BIT(i8271->CommandParameters[1], 3));
					floppy_drive_set_ready_state(img, 1, 1);

					/* step pin changed? if so perform a step in the direction indicated */
					if (((i8271->drive_control_output^i8271->CommandParameters[1]) & (1<<1))!=0)
					{
						/* step pin changed state? */

						if ((i8271->CommandParameters[1] & (1<<1))!=0)
						{
							signed int signed_tracks;

							if ((i8271->CommandParameters[1] & (1<<2))!=0)
							{
								signed_tracks = 1;
							}
							else
							{
								signed_tracks = -1;
							}

							floppy_drive_seek(img, signed_tracks);
						}
					}

					i8271->drive_control_output = i8271->CommandParameters[1];


				}
				break;

				case I8271_SPECIAL_REGISTER_DRIVE_CONTROL_INPUT_PORT:
				{

					FDC_LOG_COMMAND("Write Drive Control Input port\n");

					//                  i8271->drive_control_input = i8271->CommandParameters[1];
				}
				break;

			}

			/* write doesn't supply a result */
			i8271_command_complete(device,0,0);
		}
		break;

		case I8271_COMMAND_READ_DRIVE_STATUS:
		{
			unsigned char status;

			i8271_get_drive(device);

			/* no write fault */
			status = 0;

			status |= (1<<2) | (1<<6);

			/* these two do not appear to be set at all! ?? */

			if (i8271->intf->floppy_drive_tags[0]!=NULL) {
				if (floppy_drive_get_flag_state(device->machine().device(i8271->intf->floppy_drive_tags[0]), FLOPPY_DRIVE_READY))
				{
					status |= (1<<2);
				}
			}

			if (i8271->intf->floppy_drive_tags[1]!=NULL) {
				if (floppy_drive_get_flag_state(device->machine().device(i8271->intf->floppy_drive_tags[1]), FLOPPY_DRIVE_READY))
				{
					status |= (1<<6);
				}
			}

			/* bit 3 = 1 if write protected */
			status |= !floppy_wpt_r(img) << 3;

			/* bit 1 = 1 if head at track 0 */
			status |= !floppy_tk00_r(img) << 1;

			i8271->ResultRegister = status;
			i8271_command_complete(device,1,0);

		}
		break;

		case I8271_COMMAND_SEEK:
		{
			i8271_get_drive(device);


			i8271_seek_to_track(device,i8271->CommandParameters[0]);

			/* check for bad seek */
			i8271_timed_command_complete(device);

		}
		break;

		case I8271_COMMAND_READ_DATA_MULTI_RECORD:
		{
			/* N value as stored in ID field */
			i8271->ID_N = (i8271->CommandParameters[2]>>5) & 0x07;

			/* starting sector id */
			i8271->ID_R = i8271->CommandParameters[1];

			/* number of sectors to transfer */
			i8271->Counter = i8271->CommandParameters[2] & 0x01f;


			FDC_LOG_COMMAND("READ DATA MULTI RECORD");

			LOG(("Sector Count: %02x\n", i8271->Counter));
			LOG(("Track: %02x\n",i8271->CommandParameters[0]));
			LOG(("Sector: %02x\n", i8271->CommandParameters[1]));
			LOG(("Sector Length: %02x bytes\n", 1<<(i8271->ID_N+7)));

			i8271_get_drive(device);

			if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
			{
				/* Completion type: operation intervention probably required for recovery */
				/* Completion code: Drive not ready */
				i8271->ResultRegister = (2<<3);
				i8271_timed_command_complete(device);
			}
			else
			{
				i8271_seek_to_track(device,i8271->CommandParameters[0]);


				i8271_do_read(device);
			}

		}
		break;

		case I8271_COMMAND_READ_DATA_SINGLE_RECORD:
		{
			FDC_LOG_COMMAND("READ DATA SINGLE RECORD");

			i8271->ID_N = 0;
			i8271->Counter = 1;
			i8271->ID_R = i8271->CommandParameters[1];

			LOG(("Sector Count: %02x\n", i8271->Counter));
			LOG(("Track: %02x\n",i8271->CommandParameters[0]));
			LOG(("Sector: %02x\n", i8271->CommandParameters[1]));
			LOG(("Sector Length: %02x bytes\n", 1<<(i8271->ID_N+7)));

			i8271_get_drive(device);

			if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
			{
				/* Completion type: operation intervention probably required for recovery */
				/* Completion code: Drive not ready */
				i8271->ResultRegister = (2<<3);
				i8271_timed_command_complete(device);
			}
			else
			{
				i8271_seek_to_track(device,i8271->CommandParameters[0]);

				i8271_do_read(device);
			}

		}
		break;

		case I8271_COMMAND_WRITE_DATA_MULTI_RECORD:
		{
			/* N value as stored in ID field */
			i8271->ID_N = (i8271->CommandParameters[2]>>5) & 0x07;

			/* starting sector id */
			i8271->ID_R = i8271->CommandParameters[1];

			/* number of sectors to transfer */
			i8271->Counter = i8271->CommandParameters[2] & 0x01f;

			FDC_LOG_COMMAND("READ DATA MULTI RECORD");

			LOG(("Sector Count: %02x\n", i8271->Counter));
			LOG(("Track: %02x\n",i8271->CommandParameters[0]));
			LOG(("Sector: %02x\n", i8271->CommandParameters[1]));
			LOG(("Sector Length: %02x bytes\n", 1<<(i8271->ID_N+7)));

			i8271_get_drive(device);

            i8271->drive_control_output &=~1;

			if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
			{
				/* Completion type: operation intervention probably required for recovery */
				/* Completion code: Drive not ready */
				i8271->ResultRegister = (2<<3);
				i8271_timed_command_complete(device);
			}
			else
			{
				if (floppy_wpt_r(img) == CLEAR_LINE)
				{
					/* Completion type: operation intervention probably required for recovery */
					/* Completion code: Drive write protected */
					i8271->ResultRegister = (2<<3) | (1<<1);
					i8271_timed_command_complete(device);
				}
				else
				{
                    i8271->drive_control_output |=1;

					i8271_seek_to_track(device,i8271->CommandParameters[0]);

					i8271_do_write(device);
				}
			}
		}
		break;

		case I8271_COMMAND_WRITE_DATA_SINGLE_RECORD:
		{
			FDC_LOG_COMMAND("WRITE DATA SINGLE RECORD");

			i8271->ID_N = 0;
			i8271->Counter = 1;
			i8271->ID_R = i8271->CommandParameters[1];


			LOG(("Sector Count: %02x\n", i8271->Counter));
			LOG(("Track: %02x\n",i8271->CommandParameters[0]));
			LOG(("Sector: %02x\n", i8271->CommandParameters[1]));
			LOG(("Sector Length: %02x bytes\n", 1<<(i8271->ID_N+7)));
			i8271_get_drive(device);

            i8271->drive_control_output &=~1;

			if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
			{
				/* Completion type: operation intervention probably required for recovery */
				/* Completion code: Drive not ready */
				i8271->ResultRegister = (2<<3);
				i8271_timed_command_complete(device);
			}
			else
			{
				if (floppy_wpt_r(img) == CLEAR_LINE)
				{
					/* Completion type: operation intervention probably required for recovery */
					/* Completion code: Drive write protected */
					i8271->ResultRegister = (2<<3) | (1<<1);
					i8271_timed_command_complete(device);
				}
				else
				{

                    i8271->drive_control_output |=1;

					i8271_seek_to_track(device,i8271->CommandParameters[0]);

					i8271_do_write(device);
				}
			}

		}
		break;


		case I8271_COMMAND_READ_ID:
		{
			FDC_LOG_COMMAND("READ ID");

			LOG(("Track: %02x\n",i8271->CommandParameters[0]));
			LOG(("ID Field Count: %02x\n", i8271->CommandParameters[2]));

			i8271_get_drive(device);

			if (!floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY))
			{
				/* Completion type: operation intervention probably required for recovery */
				/* Completion code: Drive not ready */
				i8271->ResultRegister = (2<<3);
				i8271_timed_command_complete(device);
			}
			else
			{

				i8271->Counter = i8271->CommandParameters[2];

				i8271_seek_to_track(device,i8271->CommandParameters[0]);

				i8271_do_read_id(device);
			}
		}
		break;

		default:
			LOG(("ERROR Unrecognised Command\n"));
			break;
	}
}