示例#1
0
文件: i8271.c 项目: poliva/mame-rr
static int i8271_find_sector(device_t *device)
{
	device_t *img = current_image(device);
	i8271_t *i8271 = get_safe_token(device);
//  int track_count_attempt;

//  track_count_attempt
	/* find sector within one revolution of the disc - 2 index pulses */

	/* number of times we have seen index hole */
	int index_count = 0;

	/* get sector id's */
	do
    {
		chrn_id id;

		/* get next id from disc */
		if (floppy_drive_get_next_id(img, i8271->side,&id))
		{
			/* tested on Amstrad CPC - All bytes must match, otherwise
            a NO DATA error is reported */
			if (id.R == i8271->ID_R)
			{
				/* TODO: Is this correct? What about bad tracks? */
				if (id.C == i8271->CurrentTrack[i8271->drive])
				{
					i8271->data_id = id.data_id;
					return 1;
				}
				else
				{
					/* TODO: if track doesn't match, the real 8271 does a step */


					return 0;
				}
			}
		}

		 /* index set? */
		if (floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX))
		{
			index_count++;
		}

	}
	while (index_count!=2);

	/* completion type: command/drive error */
	/* completion code: sector not found */
	i8271->ResultRegister |= (3<<3);

	return 0;
}
示例#2
0
/* preamble to all sector read / write commands, returns 1 if found */
static int mc6843_address_search( device_t *device, chrn_id* id )
{
	mc6843_t* mc6843 = get_safe_token( device );
	device_t* img = mc6843_floppy_image( device );
	int r = 0;

	while ( 1 )
	{

		if ( ( ! floppy_drive_get_next_id( img, mc6843->side, id ) ) || ( id->flags & ID_FLAG_CRC_ERROR_IN_ID_FIELD ) || ( id->N != 0 ) )
		{
			/* read address error */
			LOG(( "%f mc6843_address_search: get_next_id failed\n", device->machine().time().as_double() ));
			mc6843->STRB |= 0x0a; /* set CRC error & Sector Address Undetected */
			mc6843_cmd_end( device );
			return 0;
		}

		if ( id->C != mc6843->LTAR )
		{
			/* track mismatch */
			LOG(( "%f mc6843_address_search: track mismatch: logical=%i real=%i\n", device->machine().time().as_double(), mc6843->LTAR, id->C ));
			mc6843->data[0] = id->C; /* make the track number available to the CPU */
			mc6843->STRA |= 0x20;    /* set Track Not Equal */
			mc6843_cmd_end( device );
			return 0;
		}

		if ( id->R == mc6843->SAR )
		{
			/* found! */
			LOG(( "%f mc6843_address_search: sector %i found on track %i\n", device->machine().time().as_double(), id->R, id->C ));
			if ( ! (mc6843->CMR & 0x20) )
			{
				mc6843->ISR |= 0x04; /* if no DMA, set Status Sense */
			}
			return 1;
		}

		if ( floppy_drive_get_flag_state( img, FLOPPY_DRIVE_INDEX ) )
		{
			r++;
			if ( r >= 4 )
			{
				/* time-out after 3 full revolutions */
				LOG(( "%f mc6843_address_search: no sector %i found after 3 revolutions\n", device->machine().time().as_double(), mc6843->SAR ));
				mc6843->STRB |= 0x08; /* set Sector Address Undetected */
				mc6843_cmd_end( device );
				return 0;
			}
		}
	}

	return 0; /* unreachable */
}
示例#3
0
文件: rx01.c 项目: clobber/UME
void rx01_device::command_write(UINT16 data)
{
	printf("command_write %04x\n",data);
	m_unit = BIT(data,4);
	m_interrupt = BIT(data,6);

	floppy_drive_set_ready_state(m_image[m_unit], 1,0);


	if (BIT(data,14)) // Initialize
	{
		printf("initialize\n");
		m_state = RX01_INIT;
	}
	else if (BIT(data,1)) // If GO bit is selected
	{
		m_rxcs &= ~(1<<5); // Clear done bit
		m_buf_pos = 0; // Point to start of buffer
		switch((data >> 1) & 7) {
			case 0: // Fill Buffer
					m_rxcs |= (1<<7); // Set TR Bit
					m_state = RX01_FILL;
					break;
			case 1: // Empty Buffer
					m_state = RX01_EMPTY;
					break;
			case 2: // Write Sector
			case 3: // Read Sector
			case 6: // Write Deleted Data Sector
					m_rxes &= ~(1<<6 | 1<<1 | 1<<0);// Reset bits 0, 1 and 6
					m_state = RX01_SET_SECTOR;
					break;
			case 4: // Not Used
					m_state = RX01_COMPLETE;
					break;
			case 5: // Read Status
					m_state = RX01_COMPLETE;
					m_rxdb = m_rxes;
					break;
			case 7: // Read Error Register
					m_state = RX01_COMPLETE;
					// set ready signal according to current drive status
					m_rxes |= floppy_drive_get_flag_state(m_image[m_unit], FLOPPY_DRIVE_READY) << 7;
					break;
		}
	}
示例#4
0
文件: i8271.c 项目: poliva/mame-rr
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;
	}
}