|
@@ -111,13 +111,9 @@ static uint8_t u_buf[8192];
|
|
|
static uint32_t u_cons, u_prod;
|
|
|
#define U_MASK(x) ((x)&(sizeof(u_buf)-1))
|
|
|
|
|
|
-static struct delay_params {
|
|
|
- uint16_t step_delay;
|
|
|
- uint16_t seek_settle;
|
|
|
- uint16_t motor_delay;
|
|
|
- uint16_t auto_off;
|
|
|
-} delay_params = {
|
|
|
- .step_delay = 3,
|
|
|
+static struct gw_delay delay_params = {
|
|
|
+ .select_delay = 10,
|
|
|
+ .step_delay = 3000,
|
|
|
.seek_settle = 15,
|
|
|
.motor_delay = 750,
|
|
|
.auto_off = 10000
|
|
@@ -130,7 +126,7 @@ static void step_one_out(void)
|
|
|
write_pin(step, TRUE);
|
|
|
delay_us(10);
|
|
|
write_pin(step, FALSE);
|
|
|
- delay_ms(delay_params.step_delay);
|
|
|
+ delay_us(delay_params.step_delay);
|
|
|
}
|
|
|
|
|
|
static void step_one_in(void)
|
|
@@ -140,27 +136,22 @@ static void step_one_in(void)
|
|
|
write_pin(step, TRUE);
|
|
|
delay_us(10);
|
|
|
write_pin(step, FALSE);
|
|
|
- delay_ms(delay_params.step_delay);
|
|
|
+ delay_us(delay_params.step_delay);
|
|
|
}
|
|
|
|
|
|
static int cur_cyl = -1;
|
|
|
|
|
|
-static void drive_select(void)
|
|
|
+static void drive_select(bool_t on)
|
|
|
{
|
|
|
- write_pin(sel0, TRUE);
|
|
|
- delay_us(10);
|
|
|
-}
|
|
|
-
|
|
|
-static void drive_deselect(void)
|
|
|
-{
|
|
|
- delay_us(10);
|
|
|
- write_pin(sel0, FALSE);
|
|
|
+ if (read_pin(sel0) == on)
|
|
|
+ return;
|
|
|
+ write_pin(sel0, on);
|
|
|
+ if (on)
|
|
|
+ delay_us(delay_params.select_delay);
|
|
|
}
|
|
|
|
|
|
static bool_t floppy_seek(unsigned int cyl)
|
|
|
{
|
|
|
- drive_select();
|
|
|
-
|
|
|
if ((cyl == 0) || (cur_cyl < 0)) {
|
|
|
|
|
|
unsigned int i;
|
|
@@ -171,7 +162,6 @@ static bool_t floppy_seek(unsigned int cyl)
|
|
|
}
|
|
|
cur_cyl = 0;
|
|
|
if (get_trk0() == HIGH) {
|
|
|
- drive_deselect();
|
|
|
cur_cyl = -1;
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -194,15 +184,13 @@ static bool_t floppy_seek(unsigned int cyl)
|
|
|
|
|
|
}
|
|
|
|
|
|
- drive_deselect();
|
|
|
-
|
|
|
delay_ms(delay_params.seek_settle);
|
|
|
cur_cyl = cyl;
|
|
|
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
-static void floppy_motor(bool_t on)
|
|
|
+static void drive_motor(bool_t on)
|
|
|
{
|
|
|
if (read_pin(motor) == on)
|
|
|
return;
|
|
@@ -318,7 +306,7 @@ void floppy_init(void)
|
|
|
}
|
|
|
|
|
|
static struct gw_info gw_info = {
|
|
|
- .max_index = 15, .max_cmd = CMD_GET_INDEX_TIMES,
|
|
|
+ .max_index = 15, .max_cmd = CMD_SELECT,
|
|
|
.sample_freq = SYSCLK_MHZ * 1000000u
|
|
|
};
|
|
|
|
|
@@ -433,8 +421,11 @@ static void rdata_encode_flux(void)
|
|
|
rw.ticks_since_index = ticks_since_index;
|
|
|
}
|
|
|
|
|
|
-static void floppy_read_prep(unsigned int nr_idx)
|
|
|
+static uint8_t floppy_read_prep(struct gw_read_flux *rf)
|
|
|
{
|
|
|
+ if ((rf->nr_idx == 0) || (rf->nr_idx > gw_info.max_index))
|
|
|
+ return ACK_BAD_COMMAND;
|
|
|
+
|
|
|
/* Start DMA. */
|
|
|
dma_rdata.cndtr = ARRAY_SIZE(dma.buf);
|
|
|
dma_rdata.ccr = (DMA_CCR_PL_HIGH |
|
|
@@ -449,9 +440,6 @@ static void floppy_read_prep(unsigned int nr_idx)
|
|
|
dma.cons = 0;
|
|
|
dma.prev_sample = tim_rdata->cnt;
|
|
|
|
|
|
- drive_select();
|
|
|
- floppy_motor(TRUE);
|
|
|
-
|
|
|
/* Start timer. */
|
|
|
tim_rdata->ccer = TIM_CCER_CC2E | TIM_CCER_CC2P;
|
|
|
tim_rdata->cr1 = TIM_CR1_CEN;
|
|
@@ -459,9 +447,11 @@ static void floppy_read_prep(unsigned int nr_idx)
|
|
|
index.count = 0;
|
|
|
floppy_state = ST_read_flux;
|
|
|
memset(&rw, 0, sizeof(rw));
|
|
|
- rw.nr_idx = nr_idx;
|
|
|
+ rw.nr_idx = rf->nr_idx;
|
|
|
rw.start = time_now();
|
|
|
rw.status = ACK_OKAY;
|
|
|
+
|
|
|
+ return ACK_OKAY;
|
|
|
}
|
|
|
|
|
|
static void make_read_packet(unsigned int n)
|
|
@@ -524,7 +514,6 @@ static void floppy_read(void)
|
|
|
make_read_packet(avail);
|
|
|
floppy_state = ST_command_wait;
|
|
|
floppy_end_command(rw.packet, avail+1);
|
|
|
- drive_deselect();
|
|
|
return; /* FINISHED */
|
|
|
|
|
|
}
|
|
@@ -641,27 +630,23 @@ static void floppy_process_write_packet(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void floppy_write_prep(struct gw_write_flux *wf)
|
|
|
+static uint8_t floppy_write_prep(struct gw_write_flux *wf)
|
|
|
{
|
|
|
+ if (get_wrprot() == LOW)
|
|
|
+ return ACK_WRPROT;
|
|
|
+
|
|
|
/* Initialise DMA ring indexes (consumer index is implicit). */
|
|
|
dma_wdata.cndtr = ARRAY_SIZE(dma.buf);
|
|
|
dma.prod = 0;
|
|
|
|
|
|
- drive_select();
|
|
|
- floppy_motor(TRUE);
|
|
|
-
|
|
|
floppy_state = ST_write_flux_wait_data;
|
|
|
memset(&rw, 0, sizeof(rw));
|
|
|
rw.status = ACK_OKAY;
|
|
|
|
|
|
- if (get_wrprot() == LOW) {
|
|
|
- floppy_flux_end();
|
|
|
- rw.status = ACK_WRPROT;
|
|
|
- floppy_state = ST_write_flux_drain;
|
|
|
- }
|
|
|
-
|
|
|
index.delay = time_sysclk(wf->index_delay_ticks);
|
|
|
rw.terminate_at_index = wf->terminate_at_index;
|
|
|
+
|
|
|
+ return ACK_OKAY;
|
|
|
}
|
|
|
|
|
|
static void floppy_write_wait_data(void)
|
|
@@ -787,7 +772,6 @@ static void floppy_write_drain(void)
|
|
|
u_buf[0] = rw.status;
|
|
|
floppy_state = ST_command_wait;
|
|
|
floppy_end_command(u_buf, 1);
|
|
|
- drive_deselect();
|
|
|
|
|
|
/* Reset INDEX handling. */
|
|
|
IRQ_global_disable();
|
|
@@ -808,70 +792,91 @@ static void process_command(void)
|
|
|
switch (cmd) {
|
|
|
case CMD_GET_INFO: {
|
|
|
uint8_t idx = u_buf[2];
|
|
|
- if (len != 3) goto bad_command;
|
|
|
- if (idx != 0) goto bad_command;
|
|
|
- memset(&u_buf[2], 0, 32);
|
|
|
+ uint8_t nr = u_buf[3];
|
|
|
+ if ((len != 4) || (idx != 0) || (nr > 32))
|
|
|
+ goto bad_command;
|
|
|
+ memset(&u_buf[2], 0, nr);
|
|
|
gw_info.fw_major = fw_major;
|
|
|
gw_info.fw_minor = fw_minor;
|
|
|
memcpy(&u_buf[2], &gw_info, sizeof(gw_info));
|
|
|
- resp_sz += 32;
|
|
|
+ resp_sz += nr;
|
|
|
break;
|
|
|
}
|
|
|
case CMD_SEEK: {
|
|
|
uint8_t cyl = u_buf[2];
|
|
|
- if (len != 3) goto bad_command;
|
|
|
- if (cyl > 85) goto bad_command;
|
|
|
+ if ((len != 3) || (cyl > 85))
|
|
|
+ goto bad_command;
|
|
|
u_buf[1] = floppy_seek(cyl) ? ACK_OKAY : ACK_NO_TRK0;
|
|
|
goto out;
|
|
|
}
|
|
|
case CMD_SIDE: {
|
|
|
uint8_t side = u_buf[2];
|
|
|
- if (len != 3) goto bad_command;
|
|
|
- if (side > 1) goto bad_command;
|
|
|
+ if ((len != 3) || (side > 1))
|
|
|
+ goto bad_command;
|
|
|
write_pin(side, side);
|
|
|
break;
|
|
|
}
|
|
|
- case CMD_SET_DELAYS: {
|
|
|
- if (len != (2+sizeof(delay_params))) goto bad_command;
|
|
|
- memcpy(&delay_params, &u_buf[2], sizeof(delay_params));
|
|
|
+ case CMD_SET_PARAMS: {
|
|
|
+ uint8_t idx = u_buf[2];
|
|
|
+ if ((len < 3) || (idx != PARAMS_DELAYS)
|
|
|
+ || (len > (3 + sizeof(delay_params))))
|
|
|
+ goto bad_command;
|
|
|
+ memcpy(&delay_params, &u_buf[3], len-3);
|
|
|
break;
|
|
|
}
|
|
|
- case CMD_GET_DELAYS: {
|
|
|
- if (len != 2) goto bad_command;
|
|
|
- memcpy(&u_buf[2], &delay_params, sizeof(delay_params));
|
|
|
- resp_sz += sizeof(delay_params);
|
|
|
+ case CMD_GET_PARAMS: {
|
|
|
+ uint8_t idx = u_buf[2];
|
|
|
+ uint8_t nr = u_buf[3];
|
|
|
+ if ((len != 4) || (idx != PARAMS_DELAYS)
|
|
|
+ || (nr > sizeof(delay_params)))
|
|
|
+ goto bad_command;
|
|
|
+ memcpy(&u_buf[2], &delay_params, nr);
|
|
|
+ resp_sz += nr;
|
|
|
break;
|
|
|
}
|
|
|
case CMD_MOTOR: {
|
|
|
- uint8_t state = u_buf[2];
|
|
|
- if (len != 3) goto bad_command;
|
|
|
- if (state > 1) goto bad_command;
|
|
|
- floppy_motor(state);
|
|
|
+ uint8_t mask = u_buf[2];
|
|
|
+ if ((len != 3) || (mask & ~1))
|
|
|
+ goto bad_command;
|
|
|
+ drive_motor(mask & 1);
|
|
|
break;
|
|
|
}
|
|
|
case CMD_READ_FLUX: {
|
|
|
- uint8_t nr_idx = u_buf[2];
|
|
|
- if (len != 3) goto bad_command;
|
|
|
- if ((nr_idx == 0) || (nr_idx > gw_info.max_index)) goto bad_command;
|
|
|
- floppy_read_prep(nr_idx);
|
|
|
- break;
|
|
|
+ struct gw_read_flux rf = { .nr_idx = 2 };
|
|
|
+ if ((len < 2) || (len > (2 + sizeof(rf))))
|
|
|
+ goto bad_command;
|
|
|
+ memcpy(&rf, &u_buf[2], len-2);
|
|
|
+ u_buf[1] = floppy_read_prep(&rf);
|
|
|
+ goto out;
|
|
|
}
|
|
|
case CMD_WRITE_FLUX: {
|
|
|
struct gw_write_flux wf = { 0 };
|
|
|
- if ((len < 2) || (len > (2 + sizeof(wf)))) goto bad_command;
|
|
|
+ if ((len < 2) || (len > (2 + sizeof(wf))))
|
|
|
+ goto bad_command;
|
|
|
memcpy(&wf, &u_buf[2], len-2);
|
|
|
- floppy_write_prep(&wf);
|
|
|
- break;
|
|
|
+ u_buf[1] = floppy_write_prep(&wf);
|
|
|
+ goto out;
|
|
|
+
|
|
|
}
|
|
|
case CMD_GET_FLUX_STATUS: {
|
|
|
- if (len != 2) goto bad_command;
|
|
|
+ if (len != 2)
|
|
|
+ goto bad_command;
|
|
|
u_buf[1] = rw.status;
|
|
|
goto out;
|
|
|
}
|
|
|
case CMD_GET_INDEX_TIMES: {
|
|
|
- if (len != 2) goto bad_command;
|
|
|
- memcpy(&u_buf[2], rw.index_ticks, sizeof(rw.index_ticks));
|
|
|
- resp_sz += sizeof(rw.index_ticks);
|
|
|
+ uint8_t f = u_buf[2], n = u_buf[3];
|
|
|
+ if ((len != 4) || (n > 15) || ((f+n) > gw_info.max_index))
|
|
|
+ goto bad_command;
|
|
|
+ memcpy(&u_buf[2], rw.index_ticks+f, n*4);
|
|
|
+ resp_sz += n*4;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CMD_SELECT: {
|
|
|
+ uint8_t mask = u_buf[2];
|
|
|
+ if ((len != 3) || (mask & ~1))
|
|
|
+ goto bad_command;
|
|
|
+ drive_select(mask & 1);
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
@@ -900,8 +905,8 @@ void floppy_process(void)
|
|
|
|
|
|
if (auto_off.armed && (time_since(auto_off.deadline) >= 0)) {
|
|
|
floppy_flux_end();
|
|
|
- floppy_motor(FALSE);
|
|
|
- drive_deselect();
|
|
|
+ drive_motor(FALSE);
|
|
|
+ drive_select(FALSE);
|
|
|
auto_off.armed = FALSE;
|
|
|
//gpio_write_pin(gpioa, 0, LOW);
|
|
|
//delay_ms(100); /* force disconnect */
|