dd cleanup

This commit is contained in:
Polprzewodnikowy 2021-12-16 18:25:47 +01:00
parent b7b1d1990a
commit 0bb73dac1c
4 changed files with 336 additions and 397 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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)