mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-02-16 12:19:11 +01:00
dd working
This commit is contained in:
parent
71f134178a
commit
b7b1d1990a
@ -54,6 +54,7 @@ set_global_assignment -name SDC_FILE SummerCart64.sdc
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dd.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flash.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
|
||||
|
@ -46,6 +46,8 @@ module SummerCart64 (
|
||||
logic [7:0] gpio_i;
|
||||
logic [7:0] gpio_oe;
|
||||
|
||||
logic dd_interrupt;
|
||||
|
||||
if_system sys (
|
||||
.in_clk(i_clk),
|
||||
.n64_reset(i_n64_reset),
|
||||
@ -64,6 +66,10 @@ module SummerCart64 (
|
||||
|
||||
if_flash flash ();
|
||||
|
||||
if_dd dd (
|
||||
.dd_interrupt(dd_interrupt)
|
||||
);
|
||||
|
||||
system system_inst (
|
||||
.sys(sys)
|
||||
);
|
||||
@ -82,6 +88,7 @@ module SummerCart64 (
|
||||
.flashram(flashram),
|
||||
.si(si),
|
||||
.flash(flash),
|
||||
.dd(dd),
|
||||
|
||||
.n64_pi_alel(i_n64_pi_alel),
|
||||
.n64_pi_aleh(i_n64_pi_aleh),
|
||||
@ -109,6 +116,7 @@ module SummerCart64 (
|
||||
.flashram(flashram),
|
||||
.si(si),
|
||||
.flash(flash),
|
||||
.dd(dd),
|
||||
|
||||
.gpio_o(gpio_o),
|
||||
.gpio_i(gpio_i),
|
||||
@ -131,9 +139,12 @@ module SummerCart64 (
|
||||
.sd_dat(io_sd_dat)
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
o_led = gpio_oe[0] ? gpio_o[0] : 1'bZ;
|
||||
o_n64_irq = gpio_oe[1] ? gpio_o[1] : 1'bZ;
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
|
124
fw/rtl/cpu/cpu_dd.sv
Normal file
124
fw/rtl/cpu/cpu_dd.sv
Normal file
@ -0,0 +1,124 @@
|
||||
module cpu_dd (
|
||||
if_system.sys sys,
|
||||
if_cpu_bus bus,
|
||||
if_dd.cpu dd
|
||||
);
|
||||
|
||||
const bit [8:0] M_SECTOR_BUFFER = 9'h100;
|
||||
|
||||
logic bm_ack;
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
R_SCR,
|
||||
R_CMD_DATA,
|
||||
R_HEAD_TRACK,
|
||||
R_SECTOR_INFO,
|
||||
R_DRIVE_ID
|
||||
} e_reg_id;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
if (bus.request) begin
|
||||
bus.ack <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
bus.rdata = 32'd0;
|
||||
if (bus.ack) begin
|
||||
if (bus.address[8] == M_SECTOR_BUFFER[8]) begin
|
||||
bus.rdata = dd.sector_rdata;
|
||||
end else begin
|
||||
case (bus.address[5:2])
|
||||
R_SCR: bus.rdata = {
|
||||
14'd0,
|
||||
bm_ack,
|
||||
dd.bm_micro_error,
|
||||
dd.bm_transfer_c2,
|
||||
dd.bm_transfer_data,
|
||||
dd.bm_transfer_blocks,
|
||||
dd.bm_transfer_mode,
|
||||
1'b0,
|
||||
dd.bm_stop_pending,
|
||||
1'b0,
|
||||
dd.bm_start_pending,
|
||||
dd.disk_changed,
|
||||
dd.disk_inserted,
|
||||
1'b0,
|
||||
dd.bm_pending,
|
||||
1'b0,
|
||||
dd.cmd_pending,
|
||||
1'b0,
|
||||
dd.hard_reset
|
||||
};
|
||||
R_CMD_DATA: bus.rdata = {8'd0, dd.cmd, dd.data};
|
||||
R_HEAD_TRACK: bus.rdata = {18'd0, dd.index_lock, dd.head_track};
|
||||
R_SECTOR_INFO: bus.rdata = {
|
||||
dd.sectors_in_block,
|
||||
dd.sector_size_full,
|
||||
dd.sector_size,
|
||||
dd.sector_num
|
||||
};
|
||||
R_DRIVE_ID: bus.rdata = {dd.drive_id};
|
||||
default: bus.rdata = 32'd0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
dd.sector_address = bus.address[7:2];
|
||||
dd.sector_address_valid = bus.request && bus.address[8] == M_SECTOR_BUFFER[8];
|
||||
dd.sector_write = (&bus.wmask) && dd.sector_address_valid;
|
||||
dd.sector_wdata = {bus.wdata[7:0], bus.wdata[15:8], bus.wdata[23:16], bus.wdata[31:24]};
|
||||
end
|
||||
|
||||
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;
|
||||
|
||||
if (dd.bm_interrupt_ack) begin
|
||||
bm_ack <= 1'b1;
|
||||
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[18]) begin
|
||||
bm_ack <= 1'b0;
|
||||
end
|
||||
dd.bm_micro_error <= bus.wdata[16];
|
||||
dd.bm_transfer_c2 <= bus.wdata[15];
|
||||
dd.bm_transfer_data <= bus.wdata[14];
|
||||
dd.bm_stop_clear <= bus.wdata[11];
|
||||
dd.bm_start_clear <= bus.wdata[9];
|
||||
dd.disk_changed <= bus.wdata[7];
|
||||
dd.disk_inserted <= bus.wdata[6];
|
||||
dd.bm_ready <= bus.wdata[5];
|
||||
dd.cmd_ready <= bus.wdata[3];
|
||||
dd.hard_reset_clear <= bus.wdata[1];
|
||||
end
|
||||
|
||||
R_CMD_DATA: if (&bus.wmask[1:0]) begin
|
||||
dd.cmd_data <= bus.wdata[15:0];
|
||||
end
|
||||
|
||||
R_HEAD_TRACK: if (&bus.wmask[1:0]) begin
|
||||
{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];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -6,6 +6,7 @@ module cpu_soc (
|
||||
if_flashram.cpu flashram,
|
||||
if_si.cpu si,
|
||||
if_flash.cpu flash,
|
||||
if_dd.cpu dd,
|
||||
|
||||
input [7:0] gpio_i,
|
||||
output [7:0] gpio_o,
|
||||
@ -113,6 +114,12 @@ module cpu_soc (
|
||||
.si(si)
|
||||
);
|
||||
|
||||
cpu_dd cpu_dd_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_CPU_DD].device),
|
||||
.dd(dd)
|
||||
);
|
||||
|
||||
assign sd_clk = 1'bZ;
|
||||
assign sd_cmd = 1'bZ;
|
||||
assign sd_dat = 4'bZZZZ;
|
||||
|
@ -9,6 +9,9 @@ interface if_n64_bus ();
|
||||
logic [31:0] address;
|
||||
logic [15:0] wdata;
|
||||
logic [15:0] rdata;
|
||||
logic [31:0] real_address;
|
||||
logic read_op;
|
||||
logic write_op;
|
||||
|
||||
logic device_ack [(NUM_DEVICES - 1):0];
|
||||
logic [15:0] device_rdata [(NUM_DEVICES - 1):0];
|
||||
@ -30,7 +33,11 @@ interface if_n64_bus ();
|
||||
output write,
|
||||
output address,
|
||||
output wdata,
|
||||
input rdata
|
||||
input rdata,
|
||||
|
||||
output real_address,
|
||||
output read_op,
|
||||
output write_op
|
||||
);
|
||||
|
||||
genvar n;
|
||||
@ -48,7 +55,11 @@ interface if_n64_bus ();
|
||||
input .write(write),
|
||||
input .address(address),
|
||||
input .wdata(wdata),
|
||||
output .rdata(device_rdata[n])
|
||||
output .rdata(device_rdata[n]),
|
||||
|
||||
input .real_address(real_address),
|
||||
input .read_op(read_op),
|
||||
input .write_op(write_op)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
@ -1,40 +1,154 @@
|
||||
interface if_dd();
|
||||
interface if_dd (
|
||||
output dd_interrupt
|
||||
);
|
||||
|
||||
// Sector buffer regs
|
||||
|
||||
logic [6:0] n64_sector_address;
|
||||
logic n64_sector_address_valid;
|
||||
logic n64_sector_write;
|
||||
logic [15:0] n64_sector_wdata;
|
||||
|
||||
logic [5:0] cpu_sector_address;
|
||||
logic cpu_sector_address_valid;
|
||||
logic cpu_sector_write;
|
||||
logic [31:0] cpu_sector_wdata;
|
||||
|
||||
logic [31:0] sector_rdata;
|
||||
|
||||
|
||||
// N64 controlled regs
|
||||
|
||||
logic hard_reset;
|
||||
logic cmd_request;
|
||||
logic cmd_ack;
|
||||
logic [7:0] command;
|
||||
logic [15:0] status;
|
||||
logic [15:0] data_input;
|
||||
logic [15:0] data_output;
|
||||
logic bm_request;
|
||||
logic [15:0] bm_control;
|
||||
logic [15:0] bm_status;
|
||||
logic [15:0] data;
|
||||
logic [7:0] cmd;
|
||||
logic cmd_pending;
|
||||
logic cmd_interrupt;
|
||||
logic bm_start_pending;
|
||||
logic bm_stop_pending;
|
||||
logic bm_transfer_mode;
|
||||
logic bm_transfer_blocks;
|
||||
logic bm_pending;
|
||||
logic bm_interrupt;
|
||||
logic bm_interrupt_ack;
|
||||
logic [7:0] sector_num;
|
||||
logic [7:0] sector_size;
|
||||
logic [7:0] sector_size_full;
|
||||
logic [7:0] sectors_in_block;
|
||||
|
||||
modport n64 (
|
||||
|
||||
// CPU controlled regs
|
||||
|
||||
logic hard_reset_clear;
|
||||
logic [15:0] cmd_data;
|
||||
logic cmd_ready;
|
||||
logic bm_start_clear;
|
||||
logic bm_stop_clear;
|
||||
logic bm_transfer_c2;
|
||||
logic bm_transfer_data;
|
||||
logic bm_micro_error;
|
||||
logic bm_ready;
|
||||
logic disk_inserted;
|
||||
logic disk_changed;
|
||||
logic index_lock;
|
||||
logic [12:0] head_track;
|
||||
logic [2:0] drive_id;
|
||||
|
||||
|
||||
always_comb begin
|
||||
dd_interrupt = cmd_interrupt || bm_interrupt;
|
||||
end
|
||||
|
||||
modport dd (
|
||||
output hard_reset,
|
||||
output cmd_request,
|
||||
input cmd_ack,
|
||||
output command,
|
||||
input status,
|
||||
output data_input,
|
||||
input data_output,
|
||||
output bm_request,
|
||||
output bm_control,
|
||||
input bm_status
|
||||
output data,
|
||||
output cmd,
|
||||
output cmd_pending,
|
||||
output cmd_interrupt,
|
||||
output bm_start_pending,
|
||||
output bm_stop_pending,
|
||||
output bm_transfer_mode,
|
||||
output bm_transfer_blocks,
|
||||
output bm_pending,
|
||||
output bm_interrupt,
|
||||
output bm_interrupt_ack,
|
||||
output sector_num,
|
||||
output sector_size,
|
||||
output sector_size_full,
|
||||
output sectors_in_block,
|
||||
|
||||
input hard_reset_clear,
|
||||
input cmd_data,
|
||||
input cmd_ready,
|
||||
input bm_start_clear,
|
||||
input bm_stop_clear,
|
||||
input bm_transfer_c2,
|
||||
input bm_transfer_data,
|
||||
input bm_micro_error,
|
||||
input bm_ready,
|
||||
input disk_inserted,
|
||||
input disk_changed,
|
||||
input index_lock,
|
||||
input head_track,
|
||||
input drive_id,
|
||||
|
||||
output .sector_address(n64_sector_address),
|
||||
output .sector_address_valid(n64_sector_address_valid),
|
||||
output .sector_write(n64_sector_write),
|
||||
output .sector_wdata(n64_sector_wdata),
|
||||
input sector_rdata
|
||||
);
|
||||
|
||||
modport cpu (
|
||||
input hard_reset,
|
||||
input cmd_request,
|
||||
output cmd_ack,
|
||||
input command,
|
||||
output status,
|
||||
input data_input,
|
||||
output data_output,
|
||||
input bm_request,
|
||||
input bm_control,
|
||||
output bm_status
|
||||
input data,
|
||||
input cmd,
|
||||
input cmd_pending,
|
||||
input bm_start_pending,
|
||||
input bm_stop_pending,
|
||||
input bm_transfer_mode,
|
||||
input bm_transfer_blocks,
|
||||
input bm_pending,
|
||||
input bm_interrupt_ack,
|
||||
input sector_num,
|
||||
input sector_size,
|
||||
input sector_size_full,
|
||||
input sectors_in_block,
|
||||
|
||||
output hard_reset_clear,
|
||||
output cmd_data,
|
||||
output cmd_ready,
|
||||
output bm_start_clear,
|
||||
output bm_stop_clear,
|
||||
output bm_transfer_c2,
|
||||
output bm_transfer_data,
|
||||
output bm_micro_error,
|
||||
output bm_ready,
|
||||
output disk_inserted,
|
||||
output disk_changed,
|
||||
output index_lock,
|
||||
output head_track,
|
||||
output drive_id,
|
||||
|
||||
output .sector_address(cpu_sector_address),
|
||||
output .sector_address_valid(cpu_sector_address_valid),
|
||||
output .sector_write(cpu_sector_write),
|
||||
output .sector_wdata(cpu_sector_wdata),
|
||||
input sector_rdata
|
||||
);
|
||||
|
||||
modport sector_buffer (
|
||||
input n64_sector_address,
|
||||
input n64_sector_address_valid,
|
||||
input n64_sector_write,
|
||||
input n64_sector_wdata,
|
||||
|
||||
input cpu_sector_address,
|
||||
input cpu_sector_address_valid,
|
||||
input cpu_sector_write,
|
||||
input cpu_sector_wdata,
|
||||
|
||||
output sector_rdata
|
||||
);
|
||||
|
||||
endinterface
|
||||
@ -42,9 +156,33 @@ endinterface
|
||||
|
||||
module n64_dd (
|
||||
if_system.sys sys,
|
||||
if_n64_bus bus
|
||||
if_n64_bus bus,
|
||||
if_dd.dd dd
|
||||
);
|
||||
|
||||
const bit [31:0] M_BASE = 32'h0500_0000;
|
||||
const bit [31:0] M_C2_BUFFER = M_BASE + 11'h000;
|
||||
const bit [31:0] M_SECTOR_BUFFER = M_BASE + 11'h400;
|
||||
|
||||
typedef enum bit [10:0] {
|
||||
R_DATA = 11'h500,
|
||||
R_CMD_SR = 11'h508,
|
||||
R_TRK_CUR = 11'h50C,
|
||||
R_BM_SCR = 11'h510,
|
||||
R_RESET = 11'h520,
|
||||
R_SEC_SIZ = 11'h528,
|
||||
R_SEC_INFO = 11'h530,
|
||||
R_ID = 11'h540
|
||||
} e_reg_id;
|
||||
|
||||
typedef enum bit [3:0] {
|
||||
BM_CONTROL_START_BUFFER_MANAGER = 4'd15,
|
||||
BM_CONTROL_BUFFER_MANAGER_MODE = 4'd14,
|
||||
BM_CONTROL_BUFFER_MANAGER_RESET = 4'd12,
|
||||
BM_CONTROL_BLOCK_TRANSFER = 4'd9,
|
||||
BM_CONTROL_MECHANIC_INTERRUPT_RESET = 4'd8
|
||||
} e_bm_control_id;
|
||||
|
||||
typedef enum bit [0:0] {
|
||||
S_IDLE,
|
||||
S_WAIT
|
||||
@ -53,23 +191,153 @@ module n64_dd (
|
||||
e_state state;
|
||||
|
||||
always_comb begin
|
||||
bus.rdata = 16'h0000;
|
||||
dd.sector_address = bus.address[7:1];
|
||||
dd.sector_address_valid = bus.request && bus.address[11:8] == M_SECTOR_BUFFER[11:8];
|
||||
dd.sector_write = bus.write && dd.sector_address_valid;
|
||||
dd.sector_wdata = bus.wdata;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
bus.rdata = 16'd0;
|
||||
if (bus.ack) begin
|
||||
bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000;
|
||||
if (bus.address[10:8] == M_SECTOR_BUFFER[10:8]) begin
|
||||
if (bus.address[1]) begin
|
||||
bus.rdata = dd.sector_rdata[15:0];
|
||||
end else begin
|
||||
bus.rdata = dd.sector_rdata[31:16];
|
||||
end
|
||||
end else begin
|
||||
case (bus.address[10:0])
|
||||
R_DATA: bus.rdata = dd.data;
|
||||
R_CMD_SR: bus.rdata = {
|
||||
1'b0,
|
||||
dd.bm_transfer_data,
|
||||
1'b0,
|
||||
dd.bm_transfer_c2,
|
||||
1'b0,
|
||||
dd.bm_interrupt,
|
||||
dd.cmd_interrupt,
|
||||
dd.disk_inserted,
|
||||
dd.cmd_pending,
|
||||
dd.hard_reset,
|
||||
1'b0,
|
||||
1'b0,
|
||||
1'b0,
|
||||
1'b0,
|
||||
1'b0,
|
||||
dd.disk_changed
|
||||
};
|
||||
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};
|
||||
default: bus.rdata = 16'd0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
dd.bm_interrupt_ack <= 1'b0;
|
||||
|
||||
if (dd.hard_reset_clear) begin
|
||||
dd.hard_reset <= 1'b0;
|
||||
end
|
||||
if (dd.cmd_ready) begin
|
||||
dd.data <= dd.cmd_data;
|
||||
dd.cmd_pending <= 1'b0;
|
||||
dd.cmd_interrupt <= 1'b1;
|
||||
end
|
||||
if (dd.bm_start_clear) begin
|
||||
dd.bm_start_pending <= 1'b0;
|
||||
end
|
||||
if (dd.bm_stop_clear) begin
|
||||
dd.bm_stop_pending <= 1'b0;
|
||||
end
|
||||
if (dd.bm_ready) begin
|
||||
dd.bm_pending <= 1'b0;
|
||||
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
|
||||
dd.bm_pending <= 1'b1;
|
||||
end
|
||||
if (bus.real_address == (M_SECTOR_BUFFER + {dd.sector_size[7:1], 1'b0}) && (bus.read_op || bus.write_op)) begin
|
||||
dd.bm_pending <= 1'b1;
|
||||
end
|
||||
if (bus.real_address == (M_BASE + R_CMD_SR) && bus.read_op) begin
|
||||
dd.bm_interrupt <= 1'b0;
|
||||
dd.bm_interrupt_ack <= 1'b1;
|
||||
end
|
||||
|
||||
if (sys.reset) begin
|
||||
dd.hard_reset <= 1'b1;
|
||||
dd.cmd_pending <= 1'b0;
|
||||
dd.cmd_interrupt <= 1'b0;
|
||||
dd.bm_start_pending <= 1'b0;
|
||||
dd.bm_stop_pending <= 1'b0;
|
||||
dd.bm_pending <= 1'b0;
|
||||
dd.bm_interrupt <= 1'b0;
|
||||
state <= S_IDLE;
|
||||
end else begin
|
||||
end else begin
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
if (bus.request) begin
|
||||
state <= S_WAIT;
|
||||
bus.ack <= 1'b1;
|
||||
if (bus.write) begin
|
||||
case (bus.address[10:0])
|
||||
R_DATA: begin
|
||||
dd.data <= bus.wdata;
|
||||
end
|
||||
|
||||
R_CMD_SR: begin
|
||||
dd.cmd <= bus.wdata[7:0];
|
||||
dd.cmd_pending <= 1'b1;
|
||||
end
|
||||
|
||||
R_BM_SCR: begin
|
||||
dd.sector_num <= bus.wdata[7:0];
|
||||
if (bus.wdata[BM_CONTROL_START_BUFFER_MANAGER]) begin
|
||||
dd.bm_start_pending <= 1'b1;
|
||||
dd.bm_stop_pending <= 1'b0;
|
||||
dd.bm_transfer_mode <= bus.wdata[BM_CONTROL_BUFFER_MANAGER_MODE];
|
||||
dd.bm_transfer_blocks <= bus.wdata[BM_CONTROL_BLOCK_TRANSFER];
|
||||
end
|
||||
if (bus.wdata[BM_CONTROL_BUFFER_MANAGER_RESET]) begin
|
||||
dd.bm_start_pending <= 1'b0;
|
||||
dd.bm_stop_pending <= 1'b1;
|
||||
dd.bm_transfer_mode <= 1'b0;
|
||||
dd.bm_transfer_blocks <= 1'b0;
|
||||
dd.bm_pending <= 1'b0;
|
||||
dd.bm_interrupt <= 1'b0;
|
||||
end
|
||||
if (bus.wdata[BM_CONTROL_MECHANIC_INTERRUPT_RESET]) begin
|
||||
dd.cmd_interrupt <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
R_RESET: begin
|
||||
if (bus.wdata == 16'hAAAA) begin
|
||||
dd.hard_reset <= 1'b1;
|
||||
dd.cmd_pending <= 1'b0;
|
||||
dd.cmd_interrupt <= 1'b0;
|
||||
dd.bm_start_pending <= 1'b0;
|
||||
dd.bm_stop_pending <= 1'b0;
|
||||
dd.bm_pending <= 1'b0;
|
||||
dd.bm_interrupt <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
R_SEC_SIZ: begin
|
||||
dd.sector_size <= bus.wdata[7:0];
|
||||
end
|
||||
|
||||
R_SEC_INFO: begin
|
||||
dd.sectors_in_block <= bus.wdata[15:8];
|
||||
dd.sector_size_full <= bus.wdata[7:0];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -81,3 +349,50 @@ module n64_dd (
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module n64_dd_sector_buffer (
|
||||
if_system.sys sys,
|
||||
if_dd.sector_buffer dd
|
||||
);
|
||||
|
||||
logic [5:0] sector_address;
|
||||
logic [31:0] sector_buffer [0:63];
|
||||
logic [15:0] sector_high_buffer;
|
||||
logic sector_write;
|
||||
logic [31:0] sector_wdata;
|
||||
|
||||
always_comb begin
|
||||
sector_address = 6'd0;
|
||||
sector_write = 1'b0;
|
||||
sector_wdata = 32'd0;
|
||||
|
||||
if (dd.n64_sector_address_valid) begin
|
||||
sector_address = dd.n64_sector_address[6:1];
|
||||
end else if (dd.cpu_sector_address_valid) begin
|
||||
sector_address = dd.cpu_sector_address;
|
||||
end
|
||||
|
||||
if (dd.n64_sector_write && dd.n64_sector_address[0]) begin
|
||||
sector_write = 1'b1;
|
||||
sector_wdata = {sector_high_buffer, dd.n64_sector_wdata};
|
||||
end else if (dd.cpu_sector_write) begin
|
||||
sector_write = 1'b1;
|
||||
sector_wdata = dd.cpu_sector_wdata;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (dd.n64_sector_write && !dd.n64_sector_address[0]) begin
|
||||
sector_high_buffer <= dd.n64_sector_wdata;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
dd.sector_rdata <= sector_buffer[sector_address];
|
||||
if (sector_write) begin
|
||||
sector_buffer[sector_address] <= sector_wdata;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -190,6 +190,23 @@ module n64_pi (
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
bus.read_op = read_op;
|
||||
bus.write_op = write_op;
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (aleh_op) begin
|
||||
bus.real_address[31:16] <= n64_pi_ad_input;
|
||||
end
|
||||
if (alel_op) begin
|
||||
bus.real_address[15:0] <= {n64_pi_ad_input[15:1], 1'b0};
|
||||
end
|
||||
if (read_op || write_op) begin
|
||||
bus.real_address <= bus.real_address + 2'd2;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Address decoding
|
||||
|
||||
@ -253,6 +270,11 @@ module n64_pi (
|
||||
end
|
||||
end
|
||||
if (alel_op) begin
|
||||
if (next_id == sc64::ID_N64_DD) begin
|
||||
if (|n64_pi_ad_input[15:11]) begin
|
||||
n64_pi_address_valid <= 1'b0;
|
||||
end
|
||||
end
|
||||
if (sram_selected) begin
|
||||
if (n64_pi_ad_input[15]) begin
|
||||
n64_pi_address_valid <= 1'b0;
|
||||
|
@ -6,6 +6,7 @@ module n64_soc (
|
||||
if_flashram.flashram flashram,
|
||||
if_si.si si,
|
||||
if_flash.memory flash,
|
||||
if_dd dd,
|
||||
|
||||
input n64_pi_alel,
|
||||
input n64_pi_aleh,
|
||||
@ -77,7 +78,13 @@ module n64_soc (
|
||||
|
||||
n64_dd n64_dd_inst (
|
||||
.sys(sys),
|
||||
.bus(bus.at[sc64::ID_N64_DD].device)
|
||||
.bus(bus.at[sc64::ID_N64_DD].device),
|
||||
.dd(dd)
|
||||
);
|
||||
|
||||
n64_dd_sector_buffer n64_dd_sector_buffer_inst (
|
||||
.sys(sys),
|
||||
.dd(dd)
|
||||
);
|
||||
|
||||
n64_cfg n64_cfg_inst (
|
||||
|
@ -21,6 +21,7 @@ package sc64;
|
||||
ID_CPU_SDRAM,
|
||||
ID_CPU_FLASHRAM,
|
||||
ID_CPU_SI,
|
||||
ID_CPU_DD,
|
||||
__ID_CPU_END
|
||||
} e_cpu_id;
|
||||
|
||||
|
@ -14,13 +14,13 @@ typedef struct {
|
||||
} ipl3_crc32_t;
|
||||
|
||||
static const ipl3_crc32_t ipl3_crc32[] = {
|
||||
{ .crc32 = 0x587BD543, .seed = 0xAC, .version = 0 }, // CIC5101
|
||||
{ .crc32 = 0x6170A4A1, .seed = 0x3F, .version = 1 }, // CIC6101
|
||||
{ .crc32 = 0x009E9EA3, .seed = 0x3F, .version = 1 }, // CIC7102
|
||||
{ .crc32 = 0x90BB6CB5, .seed = 0x3F, .version = 0 }, // CICx102
|
||||
{ .crc32 = 0x0B050EE0, .seed = 0x78, .version = 0 }, // CICx103
|
||||
{ .crc32 = 0x98BC2C86, .seed = 0x91, .version = 0 }, // CICx105
|
||||
{ .crc32 = 0xACC8580A, .seed = 0x85, .version = 0 }, // CICx106
|
||||
{ .crc32 = 0x587BD543, .seed = 0xAC, .version = 0 }, // 5101
|
||||
{ .crc32 = 0x6170A4A1, .seed = 0x3F, .version = 1 }, // 6101
|
||||
{ .crc32 = 0x009E9EA3, .seed = 0x3F, .version = 1 }, // 7102
|
||||
{ .crc32 = 0x90BB6CB5, .seed = 0x3F, .version = 0 }, // x102
|
||||
{ .crc32 = 0x0B050EE0, .seed = 0x78, .version = 0 }, // x103
|
||||
{ .crc32 = 0x98BC2C86, .seed = 0x91, .version = 0 }, // x105
|
||||
{ .crc32 = 0xACC8580A, .seed = 0x85, .version = 0 }, // x106
|
||||
{ .crc32 = 0x10C68B18, .seed = 0xDD, .version = 0 }, // NDXJ0
|
||||
{ .crc32 = 0xBC605D0A, .seed = 0xDD, .version = 0 }, // NDDJ0
|
||||
{ .crc32 = 0x502C4466, .seed = 0xDD, .version = 0 }, // NDDJ1
|
||||
@ -43,26 +43,13 @@ bool boot_get_tv_type (boot_info_t *info) {
|
||||
char region = ((pi_io_read(&base[15]) >> 8) & 0xFF);
|
||||
|
||||
switch (region) {
|
||||
case 'D':
|
||||
case 'F':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'P':
|
||||
case 'S':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'U':
|
||||
info->tv_type = BOOT_TV_TYPE_PAL;
|
||||
break;
|
||||
|
||||
case '7':
|
||||
case 'A':
|
||||
case 'C':
|
||||
case 'E':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'N':
|
||||
case 'U':
|
||||
info->tv_type = BOOT_TV_TYPE_NTSC;
|
||||
break;
|
||||
|
||||
|
@ -46,6 +46,7 @@ class SC64:
|
||||
__DEBUG_ID_FSD_READ = 0xF1
|
||||
__DEBUG_ID_FSD_WRITE = 0xF2
|
||||
__DEBUG_ID_FSD_SECTOR = 0xF3
|
||||
__DEBUG_ID_DD_BLOCK = 0xF5
|
||||
|
||||
|
||||
def __init__(self) -> None:
|
||||
@ -54,6 +55,7 @@ class SC64:
|
||||
self.__progress_value = None
|
||||
self.__progress_finish = None
|
||||
self.__fsd_file = None
|
||||
self.__disk_file = None
|
||||
self.__find_sc64()
|
||||
|
||||
|
||||
@ -379,7 +381,77 @@ class SC64:
|
||||
self.__fsd_file.write(data)
|
||||
|
||||
|
||||
def debug_loop(self, file: str = None) -> None:
|
||||
def __dd_track_offset(self, head_track: int) -> int:
|
||||
head = (head_track & 0x1000) >> 9
|
||||
track = head_track & 0xFFF
|
||||
dd_zone = 0
|
||||
tr_off = 0
|
||||
|
||||
if (track >= 0x425):
|
||||
dd_zone = 7 + head
|
||||
tr_off = track - 0x425
|
||||
elif (track >= 0x390):
|
||||
dd_zone = 6 + head
|
||||
tr_off = track - 0x390
|
||||
elif (track >= 0x2FB):
|
||||
dd_zone = 5 + head
|
||||
tr_off = track - 0x2FB
|
||||
elif (track >= 0x266):
|
||||
dd_zone = 4 + head
|
||||
tr_off = track - 0x266
|
||||
elif (track >= 0x1D1):
|
||||
dd_zone = 3 + head
|
||||
tr_off = track - 0x1D1
|
||||
elif (track >= 0x13C):
|
||||
dd_zone = 2 + head
|
||||
tr_off = track - 0x13C
|
||||
elif (track >= 0x9E):
|
||||
dd_zone = 1 + head
|
||||
tr_off = track - 0x9E
|
||||
else:
|
||||
dd_zone = 0 + head
|
||||
tr_off = track
|
||||
|
||||
ddStartOffset = [0x0,0x5F15E0,0xB79D00,0x10801A0,0x1523720,0x1963D80,0x1D414C0,0x20BBCE0,
|
||||
0x23196E0,0x28A1E00,0x2DF5DC0,0x3299340,0x36D99A0,0x3AB70E0,0x3E31900,0x4149200]
|
||||
ddZoneSecSize = [232,216,208,192,176,160,144,128,
|
||||
216,208,192,176,160,144,128,112]
|
||||
|
||||
return (dd_zone, ddStartOffset[dd_zone] + tr_off * ddZoneSecSize[dd_zone] * 85 * 2)
|
||||
|
||||
|
||||
# def __dd_zone_track_size(self, i) -> int:
|
||||
# # ddZoneTrackSize = [158,158,149,149,149,149,149,114,158,158,149,149,149,149,149,114]
|
||||
# ddZoneSecSize = [232,216,208,192,176,160,144,128,
|
||||
# 216,208,192,176,160,144,128,112]
|
||||
# return ddZoneSecSize[i]
|
||||
|
||||
|
||||
def __debug_process_dd_block(self, data: bytes) -> None:
|
||||
# scr = int.from_bytes(data[0:4], byteorder='big')
|
||||
current_sector = int.from_bytes(data[4:8], byteorder='little')
|
||||
head_track = int.from_bytes(data[8:12], byteorder='little')
|
||||
sector_num = int.from_bytes(data[12:16], byteorder='little')
|
||||
sector_size = int.from_bytes(data[16:20], byteorder='little')
|
||||
# sector_size_full = int.from_bytes(data[20:24], byteorder='little')
|
||||
# sectors_in_block = int.from_bytes(data[24:28], byteorder='little')
|
||||
# print(f"info: {hex(scr)}, {current_sector}, {head_track}, {sector_num}, {sector_size}, {sector_size_full}, {sectors_in_block}")
|
||||
if (self.__disk_file):
|
||||
(zone, track_offset) = self.__dd_track_offset(head_track)
|
||||
sector = 0
|
||||
sector += track_offset
|
||||
sector += (int(sector_num / 90) * 85 * (sector_size + 1)) # self.__dd_zone_track_size(zone)
|
||||
sector += ((current_sector) * (sector_size + 1))
|
||||
self.__disk_file.seek(sector)
|
||||
data_dd = self.__disk_file.read(0x100 * 85)
|
||||
if (current_sector == 0x00 or current_sector == 0x5A):
|
||||
print(f"getting sect {hex(sector)}, {hex(int.from_bytes(data_dd[0:4], byteorder='big'))}")
|
||||
self.__debug_write(self.__DEBUG_ID_DD_BLOCK, data_dd)
|
||||
else:
|
||||
self.__debug_write(self.__DEBUG_ID_DD_BLOCK, bytes(0x100))
|
||||
|
||||
|
||||
def debug_loop(self, file: str = None, disk_file: str = None) -> None:
|
||||
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
|
||||
|
||||
self.__serial.timeout = 0.01
|
||||
@ -388,6 +460,9 @@ class SC64:
|
||||
if (file):
|
||||
self.__fsd_file = open(file, "rb+")
|
||||
|
||||
if (disk_file):
|
||||
self.__disk_file = open(disk_file, "rb+")
|
||||
|
||||
start_indicator = bytearray()
|
||||
dropped_bytes = 0
|
||||
|
||||
@ -418,6 +493,8 @@ class SC64:
|
||||
self.__debug_process_fsd_write(data)
|
||||
elif (id == self.__DEBUG_ID_FSD_SECTOR):
|
||||
self.__debug_process_fsd_set_sector(data)
|
||||
elif (id == self.__DEBUG_ID_DD_BLOCK):
|
||||
self.__debug_process_dd_block(data)
|
||||
else:
|
||||
print(f"\033[35mGot unknown id: {id}, length: {length}\033[0m", file=sys.stderr)
|
||||
|
||||
@ -499,6 +576,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("-i", metavar="ddipl_path", default=None, required=False, help="path to DDIPL file")
|
||||
parser.add_argument("-q", default=None, action="store_true", required=False, help="start debug server")
|
||||
parser.add_argument("-f", metavar="sd_path", default=None, required=False, help="path to disk or file for fake SD card emulation")
|
||||
parser.add_argument("-k", metavar="disk_path", default=None, required=False, help="path to 64DD disk file")
|
||||
parser.add_argument("rom", metavar="rom_path", default=None, help="path to ROM file", nargs="?")
|
||||
|
||||
if (len(sys.argv) <= 1):
|
||||
@ -523,6 +601,7 @@ if __name__ == "__main__":
|
||||
rom_file = args.rom
|
||||
debug_server = args.q
|
||||
sd_file = args.f
|
||||
disk_file = args.k
|
||||
|
||||
firmware_backup_file = "sc64firmware.bin.bak"
|
||||
|
||||
@ -582,7 +661,7 @@ if __name__ == "__main__":
|
||||
sc64.upload_save(save_file)
|
||||
|
||||
if (debug_server):
|
||||
sc64.debug_loop(sd_file)
|
||||
sc64.debug_loop(sd_file, disk_file)
|
||||
|
||||
except SC64Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
@ -12,7 +12,7 @@ LDFLAGS = -nostartfiles -Wl,--gc-sections
|
||||
SRC_DIR = src
|
||||
BUILD_DIR = build
|
||||
|
||||
SRC_FILES = startup.S process.c usb.c cfg.c dma.c joybus.c rtc.c i2c.c flashram.c uart.c flash.c
|
||||
SRC_FILES = startup.S process.c usb.c cfg.c dma.c joybus.c rtc.c i2c.c flashram.c uart.c flash.c dd.c
|
||||
|
||||
SRCS = $(addprefix $(SRC_DIR)/, $(SRC_FILES))
|
||||
OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(patsubst %,%.o,$(SRCS))))
|
||||
|
@ -159,7 +159,7 @@ void cfg_update (uint32_t *args) {
|
||||
case CFG_ID_RECONFIGURE:
|
||||
if (args[1] == CFG->RECONFIGURE) {
|
||||
CFG->RECONFIGURE = args[1];
|
||||
__asm__ volatile (
|
||||
asm volatile (
|
||||
"ebreak \n"
|
||||
);
|
||||
}
|
||||
|
459
sw/riscv/src/dd.c
Normal file
459
sw/riscv/src/dd.c
Normal file
@ -0,0 +1,459 @@
|
||||
#include "dd.h"
|
||||
#include "uart.h"
|
||||
#include "rtc.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
#define DD_DRIVE_ID_RETAIL (0x03)
|
||||
#define DD_VERSION_RETAIL (0x0114)
|
||||
|
||||
typedef enum {
|
||||
DD_CMD_SEEK_READ = 0x01,
|
||||
DD_CMD_SEEK_WRITE = 0x02,
|
||||
DD_CMD_CLEAR_DISK_CHANGE = 0x08,
|
||||
DD_CMD_CLEAR_RESET_STATE = 0x09,
|
||||
DD_CMD_READ_VERSION = 0x0A,
|
||||
DD_CMD_SET_DISK_TYPE = 0x0B,
|
||||
DD_CMD_REQUEST_STATUS = 0x0C,
|
||||
DD_CMD_SET_RTC_YEAR_MONTH = 0x0F,
|
||||
DD_CMD_SET_RTC_DAY_HOUR = 0x10,
|
||||
DD_CMD_SET_RTC_MINUTE_SECOND = 0x11,
|
||||
DD_CMD_GET_RTC_YEAR_MONTH = 0x12,
|
||||
DD_CMD_GET_RTC_DAY_HOUR = 0x13,
|
||||
DD_CMD_GET_RTC_MINUTE_SECOND = 0x14,
|
||||
DD_CMD_READ_PROGRAM_VERSION = 0x1B,
|
||||
} 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_STOP,
|
||||
};
|
||||
|
||||
static enum state state;
|
||||
|
||||
|
||||
void dd_init (void) {
|
||||
DD->SCR &= DD_SCR_DISK_INSERTED;
|
||||
DD->HEAD_TRACK = 0;
|
||||
DD->DRIVE_ID = DD_DRIVE_ID_RETAIL;
|
||||
state = STATE_IDLE;
|
||||
}
|
||||
|
||||
|
||||
void process_dd (void) {
|
||||
uint32_t scr = DD->SCR;
|
||||
|
||||
if (scr & DD_SCR_HARD_RESET) {
|
||||
dd_init();
|
||||
}
|
||||
|
||||
if (scr & DD_SCR_CMD_PENDING) {
|
||||
dd_cmd_t cmd = (dd_cmd_t) (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");
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case DD_CMD_SEEK_READ:
|
||||
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;
|
||||
} 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;
|
||||
} else {
|
||||
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) {
|
||||
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;
|
||||
} else {
|
||||
*dst++ = (uint32_t) DD->SECTOR_NUM;
|
||||
}
|
||||
*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);
|
||||
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_STOP:
|
||||
// uart_print("state stop\r\n");
|
||||
state = STATE_IDLE;
|
||||
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);
|
||||
}
|
12
sw/riscv/src/dd.h
Normal file
12
sw/riscv/src/dd.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef DD_H__
|
||||
#define DD_H__
|
||||
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
void dd_init (void);
|
||||
void process_dd (void);
|
||||
|
||||
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
#include "rtc.h"
|
||||
#include "i2c.h"
|
||||
#include "flashram.h"
|
||||
#include "dd.h"
|
||||
#include "uart.h"
|
||||
|
||||
|
||||
@ -15,6 +16,7 @@ static const void (*process_table[])(void) = {
|
||||
process_rtc,
|
||||
process_i2c,
|
||||
process_flashram,
|
||||
process_dd,
|
||||
process_uart,
|
||||
NULL,
|
||||
};
|
||||
@ -30,6 +32,7 @@ __attribute__((naked)) void process_loop (void) {
|
||||
rtc_init();
|
||||
i2c_init();
|
||||
flashram_init();
|
||||
dd_init();
|
||||
uart_init();
|
||||
|
||||
while (1) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
|
||||
typedef volatile uint8_t io8_t;
|
||||
typedef volatile uint16_t io16_t;
|
||||
typedef volatile uint32_t io32_t;
|
||||
|
||||
|
||||
@ -189,6 +190,50 @@ typedef volatile struct joybus_regs {
|
||||
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
|
||||
|
||||
|
||||
typedef volatile struct dd_regs {
|
||||
io32_t SCR;
|
||||
io16_t DATA;
|
||||
io8_t CMD;
|
||||
io8_t __padding_1;
|
||||
io16_t HEAD_TRACK;
|
||||
io16_t __padding_2;
|
||||
io8_t SECTOR_NUM;
|
||||
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];
|
||||
io32_t SEC_BUF[64];
|
||||
} dd_regs_t;
|
||||
|
||||
#define DD_BASE (0xB0000000UL)
|
||||
#define DD ((dd_regs_t *) DD_BASE)
|
||||
|
||||
#define DD_SCR_HARD_RESET (1 << 0)
|
||||
#define DD_SCR_HARD_RESET_CLEAR (1 << 1)
|
||||
#define DD_SCR_CMD_PENDING (1 << 2)
|
||||
#define DD_SCR_CMD_READY (1 << 3)
|
||||
#define DD_SCR_BM_PENDING (1 << 4)
|
||||
#define DD_SCR_BM_READY (1 << 5)
|
||||
#define DD_SCR_DISK_INSERTED (1 << 6)
|
||||
#define DD_SCR_DISK_CHANGED (1 << 7)
|
||||
#define DD_SCR_BM_START (1 << 8)
|
||||
#define DD_SCR_BM_START_CLEAR (1 << 9)
|
||||
#define DD_SCR_BM_STOP (1 << 10)
|
||||
#define DD_SCR_BM_STOP_CLEAR (1 << 11)
|
||||
#define DD_SCR_BM_TRANSFER_MODE (1 << 12)
|
||||
#define DD_SCR_BM_TRANSFER_BLOCKS (1 << 13)
|
||||
#define DD_SCR_BM_TRANSFER_DATA (1 << 14)
|
||||
#define DD_SCR_BM_TRANSFER_C2 (1 << 15)
|
||||
#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_HEAD_TRACK_MASK (0x1FFF)
|
||||
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
|
||||
|
||||
|
||||
void reset_handler(void);
|
||||
|
||||
|
||||
|
@ -151,7 +151,7 @@ void usb_debug_reset (void) {
|
||||
p.debug_rx_busy = false;
|
||||
p.debug_tx_busy = false;
|
||||
|
||||
USB->SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
|
||||
USB->SCR = USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
|
||||
}
|
||||
|
||||
static uint8_t rx_cmd_current_byte = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user