mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-02-16 12:19:11 +01:00
dd cleanup
This commit is contained in:
parent
b7b1d1990a
commit
0bb73dac1c
@ -7,13 +7,15 @@ module cpu_dd (
|
||||
const bit [8:0] M_SECTOR_BUFFER = 9'h100;
|
||||
|
||||
logic bm_ack;
|
||||
logic [31:0] seek_timer;
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
R_SCR,
|
||||
R_CMD_DATA,
|
||||
R_HEAD_TRACK,
|
||||
R_SECTOR_INFO,
|
||||
R_DRIVE_ID
|
||||
R_DRIVE_ID,
|
||||
R_SEEK_TIMER
|
||||
} e_reg_id;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
@ -60,6 +62,7 @@ module cpu_dd (
|
||||
dd.sector_num
|
||||
};
|
||||
R_DRIVE_ID: bus.rdata = {dd.drive_id};
|
||||
R_SEEK_TIMER: bus.rdata = seek_timer;
|
||||
default: bus.rdata = 32'd0;
|
||||
endcase
|
||||
end
|
||||
@ -76,20 +79,29 @@ module cpu_dd (
|
||||
always_ff @(posedge sys.clk) begin
|
||||
dd.hard_reset_clear <= 1'b0;
|
||||
dd.cmd_ready <= 1'b0;
|
||||
dd.bm_ready <= 1'b0;
|
||||
dd.bm_start_clear <= 1'b0;
|
||||
dd.bm_stop_clear <= 1'b0;
|
||||
dd.bm_clear <= 1'b0;
|
||||
dd.bm_ready <= 1'b0;
|
||||
|
||||
if (dd.bm_interrupt_ack) begin
|
||||
bm_ack <= 1'b1;
|
||||
end
|
||||
|
||||
if (!(&seek_timer)) begin
|
||||
seek_timer <= seek_timer + 1'd1;
|
||||
end
|
||||
|
||||
if (sys.reset) begin
|
||||
bm_ack <= 1'b0;
|
||||
end else begin
|
||||
if (bus.request && (!bus.address[8])) begin
|
||||
case (bus.address[4:2])
|
||||
R_SCR: if (&bus.wmask) begin
|
||||
if (bus.wdata[20]) begin
|
||||
seek_timer <= 32'd0;
|
||||
end
|
||||
dd.bm_clear <= bus.wdata[19];
|
||||
if (bus.wdata[18]) begin
|
||||
bm_ack <= 1'b0;
|
||||
end
|
||||
@ -113,8 +125,8 @@ module cpu_dd (
|
||||
{dd.index_lock, dd.head_track} <= bus.wdata[13:0];
|
||||
end
|
||||
|
||||
R_DRIVE_ID: if (&bus.wmask[0]) begin
|
||||
dd.drive_id <= bus.wdata[2:0];
|
||||
R_DRIVE_ID: if (&bus.wmask[1:0]) begin
|
||||
dd.drive_id <= bus.wdata[15:0];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
@ -47,18 +47,20 @@ interface if_dd (
|
||||
logic bm_transfer_c2;
|
||||
logic bm_transfer_data;
|
||||
logic bm_micro_error;
|
||||
logic bm_clear;
|
||||
logic bm_ready;
|
||||
logic disk_inserted;
|
||||
logic disk_changed;
|
||||
logic index_lock;
|
||||
logic [12:0] head_track;
|
||||
logic [2:0] drive_id;
|
||||
logic [15:0] drive_id;
|
||||
|
||||
|
||||
always_comb begin
|
||||
dd_interrupt = cmd_interrupt || bm_interrupt;
|
||||
end
|
||||
|
||||
|
||||
modport dd (
|
||||
output hard_reset,
|
||||
output data,
|
||||
@ -85,6 +87,7 @@ interface if_dd (
|
||||
input bm_transfer_c2,
|
||||
input bm_transfer_data,
|
||||
input bm_micro_error,
|
||||
input bm_clear,
|
||||
input bm_ready,
|
||||
input disk_inserted,
|
||||
input disk_changed,
|
||||
@ -124,6 +127,7 @@ interface if_dd (
|
||||
output bm_transfer_data,
|
||||
output bm_micro_error,
|
||||
output bm_ready,
|
||||
output bm_clear,
|
||||
output disk_inserted,
|
||||
output disk_changed,
|
||||
output index_lock,
|
||||
@ -229,7 +233,7 @@ module n64_dd (
|
||||
};
|
||||
R_TRK_CUR: bus.rdata = {1'd0, {2{dd.index_lock}}, dd.head_track};
|
||||
R_BM_SCR: bus.rdata = {6'd0, dd.bm_micro_error, 9'd0};
|
||||
R_ID: bus.rdata = {13'd0, dd.drive_id};
|
||||
R_ID: bus.rdata = {dd.drive_id};
|
||||
default: bus.rdata = 16'd0;
|
||||
endcase
|
||||
end
|
||||
@ -254,8 +258,10 @@ module n64_dd (
|
||||
if (dd.bm_stop_clear) begin
|
||||
dd.bm_stop_pending <= 1'b0;
|
||||
end
|
||||
if (dd.bm_ready) begin
|
||||
if (dd.bm_clear) begin
|
||||
dd.bm_pending <= 1'b0;
|
||||
end
|
||||
if (dd.bm_ready) begin
|
||||
dd.bm_interrupt <= 1'b1;
|
||||
end
|
||||
if (bus.real_address == (M_C2_BUFFER + ({dd.sector_size[7:1], 1'b0} * 3'd4)) && bus.read_op) begin
|
||||
@ -269,7 +275,7 @@ module n64_dd (
|
||||
dd.bm_interrupt_ack <= 1'b1;
|
||||
end
|
||||
|
||||
if (sys.reset) begin
|
||||
if (sys.reset || sys.n64_hard_reset) begin
|
||||
dd.hard_reset <= 1'b1;
|
||||
dd.cmd_pending <= 1'b0;
|
||||
dd.cmd_interrupt <= 1'b0;
|
||||
|
@ -4,8 +4,10 @@
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
#define DD_DRIVE_ID_RETAIL (0x03)
|
||||
#define DD_DRIVE_ID_RETAIL (0x0003)
|
||||
#define DD_DRIVE_ID_DEVELOPMENT (0x0004)
|
||||
#define DD_VERSION_RETAIL (0x0114)
|
||||
#define DD_TRACK_SEEK_TIME_TICKS (10000)
|
||||
|
||||
typedef enum {
|
||||
DD_CMD_SEEK_READ = 0x01,
|
||||
@ -25,76 +27,119 @@ typedef enum {
|
||||
} dd_cmd_t;
|
||||
|
||||
|
||||
static rtc_time_t time;
|
||||
static uint8_t current_sector;
|
||||
static bool continued_transfer;
|
||||
|
||||
|
||||
static void log_bm_op (uint32_t scr) {
|
||||
if (scr & DD_SCR_BM_STOP) {
|
||||
uart_print("Got BM stop [0x");
|
||||
uart_print_02hex(current_sector); uart_print("]\r\n");
|
||||
}
|
||||
|
||||
if (scr & DD_SCR_BM_START) {
|
||||
uart_print("Got BM start [0x");
|
||||
// uart_print_02hex((DD->HEAD_TRACK >> 8) & 0xFF);
|
||||
// uart_print_02hex((DD->HEAD_TRACK >> 0) & 0xFF); uart_print(", ");
|
||||
// uart_print_02hex(DD->SECTOR_NUM); uart_print(", ");
|
||||
// uart_print_02hex(DD->SECTOR_SIZE); uart_print(", ");
|
||||
// uart_print_02hex(DD->SECTOR_SIZE_FULL); uart_print(", ");
|
||||
// uart_print_02hex(DD->SECTORS_IN_BLOCK); uart_print("]\r\n");
|
||||
|
||||
// uart_print("DD Info [0x");
|
||||
uart_print_08hex(DD->SCR); uart_print(", ");
|
||||
uart_print_02hex((DD->DATA >> 8) & 0xFF);
|
||||
uart_print_02hex((DD->DATA >> 0) & 0xFF); uart_print(", ");
|
||||
uart_print_02hex(DD->CMD); uart_print(", ");
|
||||
uart_print_02hex((DD->HEAD_TRACK >> 8) & 0xFF);
|
||||
uart_print_02hex((DD->HEAD_TRACK >> 0) & 0xFF); uart_print(", ");
|
||||
uart_print_02hex(DD->SECTOR_NUM); uart_print(", ");
|
||||
uart_print_02hex(DD->SECTOR_SIZE); uart_print(", ");
|
||||
uart_print_02hex(DD->SECTOR_SIZE_FULL); uart_print(", ");
|
||||
uart_print_02hex(DD->SECTORS_IN_BLOCK); uart_print(", ");
|
||||
uart_print_02hex(DD->DRIVE_ID); uart_print("]\r\n");
|
||||
// uart_print("Requesting data sector [0x00]\r\n");
|
||||
}
|
||||
|
||||
if (scr & DD_SCR_BM_PENDING) {
|
||||
if (current_sector < 85) {
|
||||
// uart_print("Requesting data sector [0x");
|
||||
// uart_print_02hex(current_sector); uart_print("]\r\n");
|
||||
} else if (current_sector < 85 + 4) {
|
||||
uart_print("Read C2 sector [0x");
|
||||
uart_print_02hex(current_sector); uart_print("]\r\n");
|
||||
} else if (current_sector == 85 + 4 - 1) {
|
||||
uart_print("Gap sector??\r\n");
|
||||
} else {
|
||||
uart_print("Unknown BM pending [0x");
|
||||
uart_print_02hex(current_sector); uart_print("]\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum state {
|
||||
STATE_IDLE,
|
||||
STATE_START,
|
||||
STATE_FETCH,
|
||||
STATE_WAIT,
|
||||
STATE_WAIT_2,
|
||||
STATE_TRANSFER,
|
||||
STATE_BLOCK_READ,
|
||||
STATE_BLOCK_READ_WAIT,
|
||||
STATE_SECTOR_READ,
|
||||
STATE_SECTOR_WRITE,
|
||||
STATE_BLOCK_WRITE,
|
||||
STATE_BLOCK_WRITE_WAIT,
|
||||
STATE_NEXT_BLOCK,
|
||||
STATE_STOP,
|
||||
};
|
||||
|
||||
static enum state state;
|
||||
struct process {
|
||||
enum state state;
|
||||
uint32_t track_seek_time;
|
||||
uint32_t next_seek_time;
|
||||
bool deffered_cmd_ready;
|
||||
bool bm_running;
|
||||
bool transfer_mode;
|
||||
bool full_track_transfer;
|
||||
bool starting_block;
|
||||
uint8_t current_sector;
|
||||
bool is_dev_disk;
|
||||
rtc_time_t time;
|
||||
};
|
||||
|
||||
static struct process p;
|
||||
enum {
|
||||
READ_PHASE_IDLE,
|
||||
READ_PHASE_STARTED,
|
||||
READ_PHASE_WAIT,
|
||||
} read_phase = READ_PHASE_IDLE;
|
||||
|
||||
io32_t *sdram = (io32_t *) (SDRAM_BASE + (32 * 1024 * 1024));
|
||||
|
||||
static void dd_block_read (void) {
|
||||
read_phase = READ_PHASE_STARTED;
|
||||
|
||||
io32_t *dst = sdram;
|
||||
const char *dma = "DMA@";
|
||||
const char *cmp = "CMPH";
|
||||
|
||||
if (usb_debug_tx_ready()) {
|
||||
*dst++ = *((uint32_t *) (dma));
|
||||
*dst++ = 0xF5 | (7 * 4) << 24;
|
||||
*dst++ = (uint32_t) DD->SCR;
|
||||
*dst++ = (uint32_t) p.current_sector;
|
||||
*dst++ = (uint32_t) DD->HEAD_TRACK;
|
||||
*dst++ = p.starting_block ? (DD->SECTORS_IN_BLOCK + 1) : 0;
|
||||
*dst++ = (uint32_t) DD->SECTOR_SIZE;
|
||||
*dst++ = (uint32_t) DD->SECTOR_SIZE_FULL;
|
||||
*dst++ = (uint32_t) DD->SECTORS_IN_BLOCK;
|
||||
*dst++ = *((uint32_t *) (cmp));
|
||||
usb_debug_tx_data((uint32_t) (sdram), 10 * 4);
|
||||
}
|
||||
}
|
||||
|
||||
static bool dd_block_read_done (void) {
|
||||
uint32_t type;
|
||||
size_t length;
|
||||
|
||||
if (read_phase == READ_PHASE_STARTED) {
|
||||
if (usb_debug_rx_ready(&type, &length)) {
|
||||
usb_debug_rx_data((uint32_t) (sdram), length);
|
||||
read_phase = READ_PHASE_WAIT;
|
||||
}
|
||||
return false;
|
||||
} else if (read_phase == READ_PHASE_WAIT) {
|
||||
if (!usb_debug_rx_busy()) {
|
||||
read_phase = READ_PHASE_IDLE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dd_sector_read (void) {
|
||||
io32_t *buf = DD->SEC_BUF;
|
||||
io32_t *dst = sdram;
|
||||
uint8_t sector_size = DD->SECTOR_SIZE + 1;
|
||||
|
||||
dst += ((sector_size * p.current_sector) / sizeof(io32_t));
|
||||
for (int i = 0; i < 0x100; i += 4) {
|
||||
*buf++ = *dst++;
|
||||
}
|
||||
}
|
||||
|
||||
static void dd_block_write (void) {
|
||||
uart_print("Requesting block write 0x");
|
||||
uart_print_08hex(DD->HEAD_TRACK & DD_HEAD_TRACK_MASK);
|
||||
uart_print("\r\n");
|
||||
}
|
||||
|
||||
static bool dd_block_write_done (void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dd_sector_write (void) {
|
||||
}
|
||||
|
||||
|
||||
void dd_init (void) {
|
||||
DD->SCR &= DD_SCR_DISK_INSERTED;
|
||||
DD->SCR = 0;
|
||||
DD->HEAD_TRACK = 0;
|
||||
DD->DRIVE_ID = DD_DRIVE_ID_RETAIL;
|
||||
state = STATE_IDLE;
|
||||
p.state = STATE_IDLE;
|
||||
p.track_seek_time = DD_TRACK_SEEK_TIME_TICKS;
|
||||
p.deffered_cmd_ready = false;
|
||||
p.bm_running = false;
|
||||
p.is_dev_disk = false;
|
||||
}
|
||||
|
||||
|
||||
@ -102,358 +147,226 @@ void process_dd (void) {
|
||||
uint32_t scr = DD->SCR;
|
||||
|
||||
if (scr & DD_SCR_HARD_RESET) {
|
||||
dd_init();
|
||||
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
|
||||
p.state = STATE_IDLE;
|
||||
p.deffered_cmd_ready = false;
|
||||
p.bm_running = false;
|
||||
}
|
||||
|
||||
if (scr & DD_SCR_CMD_PENDING) {
|
||||
dd_cmd_t cmd = (dd_cmd_t) (DD->CMD);
|
||||
dd_cmd_t cmd = DD->CMD;
|
||||
uint16_t data = DD->DATA;
|
||||
|
||||
if (cmd < DD_CMD_GET_RTC_YEAR_MONTH || cmd > DD_CMD_GET_RTC_MINUTE_SECOND) {
|
||||
uart_print("Got DD command: [0x");
|
||||
uart_print_02hex(cmd); uart_print("], data: [0x");
|
||||
uart_print_02hex((data >> 8) & 0xFF); uart_print_02hex((data >> 0) & 0xFF); uart_print("]\r\n");
|
||||
}
|
||||
DD->DATA = data;
|
||||
|
||||
switch (cmd) {
|
||||
case DD_CMD_SEEK_READ:
|
||||
if (p.deffered_cmd_ready) {
|
||||
if (DD->SEEK_TIMER >= p.next_seek_time) {
|
||||
p.deffered_cmd_ready = false;
|
||||
DD->HEAD_TRACK = DD_HEAD_TRACK_INDEX_LOCK | data;
|
||||
break;
|
||||
|
||||
case DD_CMD_SEEK_WRITE:
|
||||
DD->HEAD_TRACK = DD_HEAD_TRACK_INDEX_LOCK | data;
|
||||
break;
|
||||
|
||||
case DD_CMD_CLEAR_DISK_CHANGE:
|
||||
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
|
||||
break;
|
||||
|
||||
case DD_CMD_CLEAR_RESET_STATE:
|
||||
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
|
||||
DD->SCR |= DD_SCR_HARD_RESET_CLEAR;
|
||||
break;
|
||||
|
||||
case DD_CMD_READ_VERSION:
|
||||
DD->DATA = DD_VERSION_RETAIL;
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_DISK_TYPE:
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case DD_CMD_REQUEST_STATUS:
|
||||
DD->DATA = 0;
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_RTC_YEAR_MONTH:
|
||||
time.year = ((data >> 8) & 0xFF);
|
||||
time.month = (data & 0xFF);
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_RTC_DAY_HOUR:
|
||||
time.day = ((data >> 8) & 0xFF);
|
||||
time.hour = (data & 0xFF);
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_RTC_MINUTE_SECOND:
|
||||
time.minute = ((data >> 8) & 0xFF);
|
||||
time.second = (data & 0xFF);
|
||||
rtc_set_time(&time);
|
||||
break;
|
||||
|
||||
case DD_CMD_GET_RTC_YEAR_MONTH:
|
||||
DD->DATA = (time.year << 8) | time.month;
|
||||
break;
|
||||
|
||||
case DD_CMD_GET_RTC_DAY_HOUR:
|
||||
DD->DATA = (time.day << 8) | time.hour;
|
||||
break;
|
||||
|
||||
case DD_CMD_GET_RTC_MINUTE_SECOND:
|
||||
time = *rtc_get_time();
|
||||
DD->DATA = (time.minute << 8) | time.second;
|
||||
break;
|
||||
|
||||
case DD_CMD_READ_PROGRAM_VERSION:
|
||||
DD->DATA = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
DD->SCR |= DD_SCR_CMD_READY;
|
||||
}
|
||||
|
||||
// log_bm_op (scr);
|
||||
|
||||
uint16_t track = (DD->HEAD_TRACK & DD_HEAD_TRACK_MASK);
|
||||
uint8_t starting_sector = DD->SECTOR_NUM;
|
||||
bool forbidden_block = (track == 6) && (starting_sector == 0);
|
||||
|
||||
if (scr & DD_SCR_BM_ACK) {
|
||||
DD->SCR |= DD_SCR_BM_ACK_CLEAR;
|
||||
if (current_sector <= 85) {
|
||||
// if (state == STATE_TRANSFER) {
|
||||
// state = STATE_FETCH;
|
||||
// current_sector += 1;
|
||||
// }
|
||||
} else if (current_sector < 85 + 3) {
|
||||
// for (volatile int i = 0; i < 100000; i++) {
|
||||
// UART->SCR = 0;
|
||||
// }
|
||||
uart_print("issuing no C2 in freely [0x");
|
||||
uart_print_08hex(scr);
|
||||
uart_print("]\r\n");
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
current_sector += 1;
|
||||
} else if (current_sector < 85 + 4) {
|
||||
// for (volatile int i = 0; i < 100000; i++) {
|
||||
// UART->SCR = 0;
|
||||
// }
|
||||
uart_print("issuing C2 freely [0x");
|
||||
uart_print_08hex(scr);
|
||||
uart_print("]\r\n");
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
|
||||
DD->SCR |= DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_READY;
|
||||
current_sector += 1;
|
||||
DD->SCR |= DD_SCR_CMD_READY;
|
||||
}
|
||||
} else if ((cmd == DD_CMD_SEEK_READ) || (cmd == DD_CMD_SEEK_WRITE)) {
|
||||
int track_distance = abs((DD->HEAD_TRACK & DD_TRACK_MASK) - (data & DD_TRACK_MASK));
|
||||
p.next_seek_time = track_distance * p.track_seek_time;
|
||||
p.deffered_cmd_ready = true;
|
||||
DD->HEAD_TRACK &= ~(DD_HEAD_TRACK_INDEX_LOCK);
|
||||
DD->SCR |= DD_SCR_SEEK_TIMER_RESET;
|
||||
} else {
|
||||
uart_print("gap sector imaginary [0x");
|
||||
uart_print_08hex(scr);
|
||||
uart_print("]\r\n");
|
||||
current_sector = 0;
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
if (continued_transfer) {
|
||||
state = STATE_STOP;
|
||||
} else {
|
||||
if (DD->SCR & DD_SCR_BM_TRANSFER_BLOCKS) {
|
||||
continued_transfer = true;
|
||||
state = STATE_FETCH;
|
||||
switch (cmd) {
|
||||
case DD_CMD_CLEAR_DISK_CHANGE:
|
||||
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
|
||||
break;
|
||||
|
||||
case DD_CMD_CLEAR_RESET_STATE:
|
||||
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
|
||||
DD->SCR |= DD_SCR_HARD_RESET_CLEAR;
|
||||
break;
|
||||
|
||||
case DD_CMD_READ_VERSION:
|
||||
DD->DATA = DD_VERSION_RETAIL;
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_DISK_TYPE:
|
||||
break;
|
||||
|
||||
case DD_CMD_REQUEST_STATUS:
|
||||
DD->DATA = 0;
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_RTC_YEAR_MONTH:
|
||||
p.time.year = ((data >> 8) & 0xFF);
|
||||
p.time.month = (data & 0xFF);
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_RTC_DAY_HOUR:
|
||||
p.time.day = ((data >> 8) & 0xFF);
|
||||
p.time.hour = (data & 0xFF);
|
||||
break;
|
||||
|
||||
case DD_CMD_SET_RTC_MINUTE_SECOND:
|
||||
p.time.minute = ((data >> 8) & 0xFF);
|
||||
p.time.second = (data & 0xFF);
|
||||
rtc_set_time(&p.time);
|
||||
break;
|
||||
|
||||
case DD_CMD_GET_RTC_YEAR_MONTH:
|
||||
DD->DATA = (p.time.year << 8) | p.time.month;
|
||||
break;
|
||||
|
||||
case DD_CMD_GET_RTC_DAY_HOUR:
|
||||
DD->DATA = (p.time.day << 8) | p.time.hour;
|
||||
break;
|
||||
|
||||
case DD_CMD_GET_RTC_MINUTE_SECOND:
|
||||
p.time = *rtc_get_time();
|
||||
DD->DATA = (p.time.minute << 8) | p.time.second;
|
||||
break;
|
||||
|
||||
case DD_CMD_READ_PROGRAM_VERSION:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DD->SCR |= DD_SCR_CMD_READY;
|
||||
}
|
||||
} else {
|
||||
if (scr & DD_SCR_BM_STOP) {
|
||||
DD->SCR |= DD_SCR_BM_STOP_CLEAR;
|
||||
DD->SCR &= ~(DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
p.state = STATE_STOP;
|
||||
} else if (scr & DD_SCR_BM_START) {
|
||||
DD->SCR |= DD_SCR_BM_CLEAR | DD_SCR_BM_ACK_CLEAR | DD_SCR_BM_START_CLEAR;
|
||||
DD->SCR &= ~(DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
p.state = STATE_START;
|
||||
p.transfer_mode = (scr & DD_SCR_BM_TRANSFER_MODE);
|
||||
p.full_track_transfer = (scr & DD_SCR_BM_TRANSFER_BLOCKS);
|
||||
p.starting_block = (DD->SECTOR_NUM == (DD->SECTORS_IN_BLOCK + 1));
|
||||
} else if (p.bm_running) {
|
||||
if (scr & DD_SCR_BM_PENDING) {
|
||||
DD->SCR |= DD_SCR_BM_CLEAR;
|
||||
if (p.transfer_mode) {
|
||||
if (p.current_sector < (DD->SECTORS_IN_BLOCK - 4)) {
|
||||
p.state = STATE_SECTOR_READ;
|
||||
} else if (p.current_sector == (DD->SECTORS_IN_BLOCK - 4)) {
|
||||
p.current_sector += 1;
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
} else if (p.current_sector == DD->SECTORS_IN_BLOCK) {
|
||||
p.state = STATE_NEXT_BLOCK;
|
||||
}
|
||||
} else {
|
||||
state = STATE_STOP;
|
||||
if (p.current_sector < (DD->SECTORS_IN_BLOCK - 4)) {
|
||||
p.state = STATE_SECTOR_WRITE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scr & DD_SCR_BM_ACK) {
|
||||
DD->SCR |= DD_SCR_BM_ACK_CLEAR;
|
||||
if (p.transfer_mode) {
|
||||
if ((p.current_sector <= (DD->SECTORS_IN_BLOCK - 4))) {
|
||||
} else if (p.current_sector < (DD->SECTORS_IN_BLOCK - 1)) {
|
||||
p.current_sector += 1;
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
} else if (p.current_sector < DD->SECTORS_IN_BLOCK) {
|
||||
p.current_sector += 1;
|
||||
DD->SCR |= DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_READY;
|
||||
}
|
||||
} else {
|
||||
if (p.current_sector == (DD->SECTORS_IN_BLOCK - 4)) {
|
||||
p.state = STATE_STOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scr & DD_SCR_BM_STOP) {
|
||||
DD->SCR |= DD_SCR_BM_STOP_CLEAR;
|
||||
DD->SCR &= ~(DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
state = STATE_STOP;
|
||||
} else if (scr & DD_SCR_BM_START) {
|
||||
DD->SCR |= DD_SCR_BM_START_CLEAR;
|
||||
DD->SCR &= ~(DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
|
||||
if (forbidden_block) {
|
||||
DD->SCR |= DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_READY;
|
||||
} else {
|
||||
// kick off transfer here
|
||||
// DD->SCR |= DD_SCR_BM_TRANSFER_DATA;
|
||||
state = STATE_START;
|
||||
}
|
||||
|
||||
continued_transfer = false;
|
||||
current_sector = 0;
|
||||
|
||||
// current_sector = 1;
|
||||
} else if (scr & DD_SCR_BM_PENDING) {
|
||||
if (forbidden_block) {
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
} else {
|
||||
if (current_sector < 85) {
|
||||
if (state == STATE_TRANSFER) {
|
||||
state = STATE_FETCH;
|
||||
// current_sector += 1;
|
||||
}
|
||||
} else if (current_sector == 85) {
|
||||
// uart_print("issuing no C2 in bm_pending\r\n");
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
current_sector += 1;
|
||||
} else if (current_sector < 85 + 4) {
|
||||
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
|
||||
// DD->SCR |= DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_READY;
|
||||
// current_sector += 1;
|
||||
} else {
|
||||
uart_print("gap sector read\r\n");
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
// DD->SCR |= DD_SCR_BM_READY;
|
||||
current_sector = 0;
|
||||
state = STATE_STOP;
|
||||
}
|
||||
|
||||
// else {
|
||||
// DD->SCR |= DD_SCR_BM_READY;
|
||||
// state = STATE_STOP;
|
||||
// current_sector = 0;
|
||||
// }
|
||||
}
|
||||
// if (current_sector < 85) {
|
||||
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
|
||||
// DD->SCR |= DD_SCR_BM_TRANSFER_DATA;
|
||||
// } else if (current_sector < 85 + 4) {
|
||||
// } else if (current_sector == 88) {
|
||||
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
|
||||
// DD->SCR |= DD_SCR_BM_TRANSFER_C2;
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// current_sector += 1;
|
||||
|
||||
// DD->SCR |= DD_SCR_BM_READY;
|
||||
|
||||
|
||||
// else {
|
||||
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA);
|
||||
// }
|
||||
|
||||
// if (forbidden_block) {
|
||||
// DD->SCR |= DD_SCR_BM_READY;
|
||||
// } else {
|
||||
// // request more data here
|
||||
// DD->SCR |= DD_SCR_BM_READY;
|
||||
// }
|
||||
}
|
||||
|
||||
// else if (current_sector < 85 + 4) {
|
||||
// }
|
||||
|
||||
io32_t *sdram = (io32_t *) (SDRAM_BASE + (32 * 1024 * 1024));
|
||||
io32_t *dst = sdram;
|
||||
const char *dma = "DMA@";
|
||||
const char *cmp = "CMPH";
|
||||
io32_t *buf = DD->SEC_BUF;
|
||||
|
||||
switch (state) {
|
||||
switch (p.state) {
|
||||
case STATE_IDLE:
|
||||
break;
|
||||
|
||||
case STATE_START:
|
||||
usb_debug_reset();
|
||||
// if (usb_debug_tx_ready()) {
|
||||
// uart_print("state start\r\n");
|
||||
// current_sector = 0;
|
||||
state = STATE_FETCH;
|
||||
// }
|
||||
break;
|
||||
|
||||
case STATE_FETCH:
|
||||
if (current_sector != 0) {
|
||||
state = STATE_WAIT_2;
|
||||
} else if (usb_debug_tx_ready()) {
|
||||
// uart_print("state fetch\r\n");
|
||||
*dst++ = *((uint32_t *) (dma));
|
||||
*dst++ = 0xF5 | (7 * 4) << 24;
|
||||
*dst++ = (uint32_t) DD->SCR;
|
||||
*dst++ = (uint32_t) current_sector;
|
||||
*dst++ = (uint32_t) DD->HEAD_TRACK;
|
||||
if (continued_transfer) {
|
||||
*dst++ = DD->SECTOR_NUM == 0x5A ? 0 : 0x5A;
|
||||
p.bm_running = true;
|
||||
p.current_sector = 0;
|
||||
if (p.transfer_mode) {
|
||||
if (!p.is_dev_disk && ((DD->HEAD_TRACK & DD_HEAD_TRACK_MASK) == 6) && !p.starting_block) {
|
||||
p.state = STATE_SECTOR_READ;
|
||||
DD->SCR |= DD_SCR_BM_MICRO_ERROR;
|
||||
} else {
|
||||
*dst++ = (uint32_t) DD->SECTOR_NUM;
|
||||
p.state = STATE_BLOCK_READ;
|
||||
DD->SCR |= DD_SCR_BM_TRANSFER_DATA;
|
||||
}
|
||||
*dst++ = (uint32_t) DD->SECTOR_SIZE;
|
||||
*dst++ = (uint32_t) DD->SECTOR_SIZE_FULL;
|
||||
*dst++ = (uint32_t) DD->SECTORS_IN_BLOCK;
|
||||
*dst++ = *((uint32_t *) (cmp));
|
||||
usb_debug_tx_data((uint32_t) (sdram), 10 * 4);
|
||||
state = STATE_WAIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WAIT: {
|
||||
uint32_t type;
|
||||
size_t length;
|
||||
// if (current_sector != 0) {}
|
||||
if (usb_debug_rx_ready(&type, &length)) {
|
||||
usb_debug_rx_data((uint32_t) (sdram), length);
|
||||
state = STATE_WAIT_2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WAIT_2:
|
||||
if (current_sector != 0) {
|
||||
uint8_t sector_size = DD->SECTOR_SIZE + 1;
|
||||
dst += ((sector_size * current_sector) / sizeof(io32_t));
|
||||
for (int i = 0; i < sector_size; i += 4) {
|
||||
*buf++ = *dst++;
|
||||
}
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
|
||||
} else {
|
||||
p.state = STATE_IDLE;
|
||||
DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY;
|
||||
state = STATE_TRANSFER;
|
||||
current_sector += 1;
|
||||
} else if (!usb_debug_rx_busy()) {
|
||||
// uart_print("state wait 2\r\n");
|
||||
uint8_t sector_size = DD->SECTOR_SIZE + 1;
|
||||
for (int i = 0; i < sector_size; i += 4) {
|
||||
// uint32_t datat = *dst++;
|
||||
// *buf++ = ((datat>>24)&0xff) | // move byte 3 to byte 0
|
||||
// ((datat<<8)&0xff0000) | // move byte 1 to byte 2
|
||||
// ((datat>>8)&0xff00) | // move byte 2 to byte 1
|
||||
// ((datat<<24)&0xff000000); // byte 0 to byte 3
|
||||
*buf++ = *dst++;
|
||||
}
|
||||
// if (current_sector < 85) {
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
|
||||
DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY;
|
||||
// } else {
|
||||
// uart_print("shouldn't be here");
|
||||
// }
|
||||
state = STATE_TRANSFER;
|
||||
current_sector += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
// case STATE_TRANSFER:
|
||||
// break;
|
||||
case STATE_BLOCK_READ:
|
||||
if (dd_block_read_done()) {
|
||||
dd_block_read();
|
||||
p.state = STATE_BLOCK_READ_WAIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_BLOCK_READ_WAIT:
|
||||
if (dd_block_read_done()) {
|
||||
p.state = STATE_SECTOR_READ;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_SECTOR_READ:
|
||||
dd_sector_read();
|
||||
p.state = STATE_IDLE;
|
||||
p.current_sector += 1;
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
break;
|
||||
|
||||
case STATE_SECTOR_WRITE:
|
||||
dd_sector_write();
|
||||
p.current_sector += 1;
|
||||
if (p.current_sector < (DD->SECTORS_IN_BLOCK - 4)) {
|
||||
p.state = STATE_IDLE;
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
} else {
|
||||
p.state = STATE_BLOCK_WRITE;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_BLOCK_WRITE:
|
||||
if (dd_block_write_done()) {
|
||||
dd_block_write();
|
||||
p.state = STATE_BLOCK_WRITE_WAIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_BLOCK_WRITE_WAIT:
|
||||
if (dd_block_write_done()) {
|
||||
p.state = STATE_NEXT_BLOCK;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_NEXT_BLOCK:
|
||||
if (p.full_track_transfer) {
|
||||
p.state = STATE_START;
|
||||
p.full_track_transfer = false;
|
||||
p.starting_block = !p.starting_block;
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
|
||||
} else {
|
||||
if (p.transfer_mode) {
|
||||
p.state = STATE_STOP;
|
||||
} else {
|
||||
p.state = STATE_IDLE;
|
||||
DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
|
||||
DD->SCR |= DD_SCR_BM_READY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_STOP:
|
||||
// uart_print("state stop\r\n");
|
||||
state = STATE_IDLE;
|
||||
p.state = STATE_IDLE;
|
||||
p.bm_running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// current_sector = 0;
|
||||
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2);
|
||||
// DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY;
|
||||
// if (current_sector < 85) {
|
||||
// } else if (current_sector == 85) {
|
||||
// DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA);
|
||||
// DD->SCR |= DD_SCR_BM_TRANSFER_C2;
|
||||
// } else if (current_sector == 85 + 4) {
|
||||
// } else {
|
||||
// }
|
||||
|
||||
// current_sector += 1;
|
||||
|
||||
// DD->SCR |= DD_SCR_BM_READY;
|
||||
|
||||
|
||||
void usb_print (const char *text) {
|
||||
char *mmm = text;
|
||||
int length = 0;
|
||||
|
||||
while (*mmm++ != 0) {
|
||||
++length;
|
||||
}
|
||||
|
||||
const char *dma = "DMA@";
|
||||
const char *cmp = "CMPH";
|
||||
|
||||
io32_t *dst = &SDRAM;
|
||||
uint32_t *src = (uint32_t *) (text);
|
||||
|
||||
*dst++ = *((uint32_t *)dma);
|
||||
*dst++ = 0x01 | (length & 0xFF) << 24;
|
||||
|
||||
int i = 0;
|
||||
for (; i < length; i += 4) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
*dst++ = *((uint32_t *)cmp);
|
||||
|
||||
usb_debug_tx_data(0, i + 12);
|
||||
}
|
||||
|
@ -4,9 +4,13 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#define CPU_FREQ (100000000UL)
|
||||
|
||||
|
||||
typedef volatile uint8_t io8_t;
|
||||
typedef volatile uint16_t io16_t;
|
||||
typedef volatile uint32_t io32_t;
|
||||
@ -201,9 +205,10 @@ typedef volatile struct dd_regs {
|
||||
io8_t SECTOR_SIZE;
|
||||
io8_t SECTOR_SIZE_FULL;
|
||||
io8_t SECTORS_IN_BLOCK;
|
||||
io8_t DRIVE_ID;
|
||||
io8_t __padding_3[3];
|
||||
io32_t __padding_4[59];
|
||||
io16_t DRIVE_ID;
|
||||
io16_t __padding_3;
|
||||
io32_t SEEK_TIMER;
|
||||
io32_t __padding_4[58];
|
||||
io32_t SEC_BUF[64];
|
||||
} dd_regs_t;
|
||||
|
||||
@ -229,7 +234,10 @@ typedef volatile struct dd_regs {
|
||||
#define DD_SCR_BM_MICRO_ERROR (1 << 16)
|
||||
#define DD_SCR_BM_ACK (1 << 17)
|
||||
#define DD_SCR_BM_ACK_CLEAR (1 << 18)
|
||||
#define DD_SCR_BM_CLEAR (1 << 19)
|
||||
#define DD_SCR_SEEK_TIMER_RESET (1 << 20)
|
||||
|
||||
#define DD_TRACK_MASK (0x0FFF)
|
||||
#define DD_HEAD_TRACK_MASK (0x1FFF)
|
||||
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user