dd write works

This commit is contained in:
Polprzewodnikowy 2021-12-17 02:10:08 +01:00
parent 0bb73dac1c
commit 099d0bc91c
4 changed files with 113 additions and 69 deletions

View File

@ -29,7 +29,12 @@ module cpu_dd (
bus.rdata = 32'd0;
if (bus.ack) begin
if (bus.address[8] == M_SECTOR_BUFFER[8]) begin
bus.rdata = dd.sector_rdata;
bus.rdata = {
dd.sector_rdata[7:0],
dd.sector_rdata[15:8],
dd.sector_rdata[23:16],
dd.sector_rdata[31:24]
};
end else begin
case (bus.address[5:2])
R_SCR: bus.rdata = {

View File

@ -48,6 +48,8 @@ class SC64:
__DEBUG_ID_FSD_SECTOR = 0xF3
__DEBUG_ID_DD_BLOCK = 0xF5
__DD_USER_SECTORS_IN_BLOCK = 85
def __init__(self) -> None:
self.__serial = None
@ -381,7 +383,8 @@ class SC64:
self.__fsd_file.write(data)
def __dd_track_offset(self, head_track: int) -> int:
def __dd_track_offset(self, head_track: int, sector_size: int) -> int:
# shamelessly stolen from MAME implementation, to be rewritten
head = (head_track & 0x1000) >> 9
track = head_track & 0xFFF
dd_zone = 0
@ -412,43 +415,52 @@ class SC64:
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]
ddStartOffset = [
0x0000000,
0x05F15E0,
0x0B79D00,
0x10801A0,
0x1523720,
0x1963D80,
0x1D414C0,
0x20BBCE0,
0x23196E0,
0x28A1E00,
0x2DF5DC0,
0x3299340,
0x36D99A0,
0x3AB70E0,
0x3E31900,
0x4149200
]
return (dd_zone, ddStartOffset[dd_zone] + tr_off * ddZoneSecSize[dd_zone] * 85 * 2)
return ddStartOffset[dd_zone] + tr_off * sector_size * self.__DD_USER_SECTORS_IN_BLOCK * 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 __dd_calculate_file_offset(self, head_track: int, starting_block: int, sector_size: int) -> int:
offset = self.__dd_track_offset(head_track, sector_size)
offset += starting_block * self.__DD_USER_SECTORS_IN_BLOCK * sector_size
return offset
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}")
transfer_mode = int.from_bytes(data[0:4], byteorder='little')
head_track = int.from_bytes(data[4:6], byteorder='little')
starting_block = int.from_bytes(data[6:7], byteorder='little')
sector_size = int.from_bytes(data[7:8], byteorder='little')
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)
file_offset = self.__dd_calculate_file_offset(head_track, starting_block, sector_size)
self.__disk_file.seek(file_offset)
if (transfer_mode):
block_data = self.__disk_file.read(sector_size * self.__DD_USER_SECTORS_IN_BLOCK)
self.__debug_write(self.__DEBUG_ID_DD_BLOCK, block_data)
else:
self.__debug_write(self.__DEBUG_ID_DD_BLOCK, bytes(0x100))
block_data = self.__read_long(sector_size * self.__DD_USER_SECTORS_IN_BLOCK)
self.__disk_file.write(block_data)
else:
if (transfer_mode):
self.__debug_write(self.__DEBUG_ID_DD_BLOCK, bytes(4))
def debug_loop(self, file: str = None, disk_file: str = None) -> None:

View File

@ -1,5 +1,4 @@
#include "dd.h"
#include "uart.h"
#include "rtc.h"
#include "usb.h"
@ -7,7 +6,10 @@
#define DD_DRIVE_ID_RETAIL (0x0003)
#define DD_DRIVE_ID_DEVELOPMENT (0x0004)
#define DD_VERSION_RETAIL (0x0114)
#define DD_TRACK_SEEK_TIME_TICKS (10000)
#define DD_POWER_UP_DELAY_TICKS (320000000UL) // 3.2 s
#define DD_TRACK_SEEK_TIME_TICKS (10000) // 0.1 ms
#define DEFAULT_DD_BUFFER_OFFSET (0x03BD8000UL)
#define USB_DEBUG_ID_DD_BLOCK (0xF5)
typedef enum {
DD_CMD_SEEK_READ = 0x01,
@ -44,6 +46,7 @@ struct process {
enum state state;
uint32_t track_seek_time;
uint32_t next_seek_time;
bool power_up_delay;
bool deffered_cmd_ready;
bool bm_running;
bool transfer_mode;
@ -52,37 +55,32 @@ struct process {
uint8_t current_sector;
bool is_dev_disk;
rtc_time_t time;
io32_t *buffer;
};
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;
io32_t *dst = p.buffer;
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++ = (((2 * 4) << 24) | USB_DEBUG_ID_DD_BLOCK);
*dst++ = p.transfer_mode;
*dst++ = (((DD->SECTOR_SIZE + 1) << 24) | (p.starting_block << 16) | DD->HEAD_TRACK);
*dst++ = *((uint32_t *) (cmp));
usb_debug_tx_data((uint32_t) (sdram), 10 * 4);
}
usb_debug_tx_data((uint32_t) (p.buffer), (5 * 4));
}
static bool dd_block_read_done (void) {
@ -91,7 +89,7 @@ static bool dd_block_read_done (void) {
if (read_phase == READ_PHASE_STARTED) {
if (usb_debug_rx_ready(&type, &length)) {
usb_debug_rx_data((uint32_t) (sdram), length);
usb_debug_rx_data((uint32_t) (p.buffer), length);
read_phase = READ_PHASE_WAIT;
}
return false;
@ -107,39 +105,64 @@ static bool dd_block_read_done (void) {
}
static void dd_sector_read (void) {
io32_t *buf = DD->SEC_BUF;
io32_t *dst = sdram;
uint8_t sector_size = DD->SECTOR_SIZE + 1;
io32_t *src = p.buffer;
io32_t *dst = DD->SECTOR_BUFFER;
dst += ((sector_size * p.current_sector) / sizeof(io32_t));
for (int i = 0; i < 0x100; i += 4) {
*buf++ = *dst++;
uint8_t sector_size = ((DD->SECTOR_SIZE + 1) / sizeof(io32_t));
src += (sector_size * p.current_sector);
for (int i = 0; i < sector_size; i++) {
*dst++ = *src++;
}
}
static void dd_sector_write (void) {
io32_t *src = DD->SECTOR_BUFFER;
io32_t *dst = p.buffer + 4;
uint8_t sector_size = ((DD->SECTOR_SIZE + 1) / sizeof(io32_t));
dst += (sector_size * p.current_sector);
for (int i = 0; i < sector_size; i++) {
*dst++ = *src++;
}
}
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");
io32_t *dst = p.buffer;
const char *dma = "DMA@";
const char *cmp = "CMPH";
uint32_t block_length = ((DD->SECTOR_SIZE + 1) * 85);
*dst++ = *((uint32_t *) (dma));
*dst++ = (((2 * 4) << 24) | USB_DEBUG_ID_DD_BLOCK);
*dst++ = p.transfer_mode;
*dst++ = (((DD->SECTOR_SIZE + 1) << 24) | (p.starting_block << 16) | DD->HEAD_TRACK);
dst += block_length / 4;
*dst++ = *((uint32_t *) (cmp));
usb_debug_tx_data((uint32_t) (p.buffer), ((5 * 4) + block_length));
}
static bool dd_block_write_done (void) {
return true;
}
static void dd_sector_write (void) {
return usb_debug_tx_ready();
}
void dd_init (void) {
DD->SCR = 0;
DD->SCR = DD_SCR_DISK_INSERTED;
DD->HEAD_TRACK = 0;
DD->DRIVE_ID = DD_DRIVE_ID_RETAIL;
p.state = STATE_IDLE;
p.track_seek_time = DD_TRACK_SEEK_TIME_TICKS;
p.power_up_delay = true;
p.deffered_cmd_ready = false;
p.bm_running = false;
p.is_dev_disk = false;
p.buffer = (io32_t *) (SDRAM_BASE + DEFAULT_DD_BUFFER_OFFSET);
}
@ -148,7 +171,9 @@ void process_dd (void) {
if (scr & DD_SCR_HARD_RESET) {
DD->SCR &= ~(DD_SCR_DISK_CHANGED);
DD->HEAD_TRACK = 0;
p.state = STATE_IDLE;
p.power_up_delay = true;
p.deffered_cmd_ready = false;
p.bm_running = false;
}
@ -167,7 +192,12 @@ void process_dd (void) {
}
} 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;
if (p.power_up_delay) {
p.power_up_delay = false;
p.next_seek_time += DD_POWER_UP_DELAY_TICKS;
} else {
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;

View File

@ -8,9 +8,6 @@
#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;
@ -209,7 +206,7 @@ typedef volatile struct dd_regs {
io16_t __padding_3;
io32_t SEEK_TIMER;
io32_t __padding_4[58];
io32_t SEC_BUF[64];
io32_t SECTOR_BUFFER[64];
} dd_regs_t;
#define DD_BASE (0xB0000000UL)