|
@@ -63,11 +63,21 @@ static struct {
|
|
|
|
|
|
#define irq_index 23
|
|
|
void IRQ_23(void) __attribute__((alias("IRQ_INDEX_changed"))); /* EXTI9_5 */
|
|
|
-static volatile struct index {
|
|
|
- unsigned int count;
|
|
|
- unsigned int rdata_cnt;
|
|
|
+static struct index {
|
|
|
+ /* Main code can reset this at will. */
|
|
|
+ volatile unsigned int count;
|
|
|
+ /* For synchronising index pulse reporting to the RDATA flux stream. */
|
|
|
+ volatile unsigned int rdata_cnt;
|
|
|
+ /* Following fields are for delayed-index writes. */
|
|
|
+ unsigned int delay;
|
|
|
+ struct timer delay_timer;
|
|
|
+ time_t timestamp;
|
|
|
} index;
|
|
|
|
|
|
+#define irq_index_delay 31
|
|
|
+void IRQ_31(void) __attribute__((alias("IRQ_INDEX_delay")));
|
|
|
+static void index_delay_timer(void *unused);
|
|
|
+
|
|
|
/* A DMA buffer for running a timer associated with a floppy-data I/O pin. */
|
|
|
static struct dma_ring {
|
|
|
/* Indexes into the buf[] ring buffer. */
|
|
@@ -261,7 +271,10 @@ void floppy_init(void)
|
|
|
/* PB[15:0] -> EXT[15:0] */
|
|
|
afio->exticr1 = afio->exticr2 = afio->exticr3 = afio->exticr4 = 0x1111;
|
|
|
|
|
|
- /* Configure INDEX-changed IRQ. */
|
|
|
+ /* Configure INDEX-changed IRQs and timer. */
|
|
|
+ timer_init(&index.delay_timer, index_delay_timer, NULL);
|
|
|
+ IRQx_set_prio(irq_index_delay, TIMER_IRQ_PRI);
|
|
|
+ IRQx_enable(irq_index_delay);
|
|
|
exti->rtsr = 0;
|
|
|
exti->imr = exti->ftsr = m(pin_index);
|
|
|
IRQx_set_prio(irq_index, INDEX_IRQ_PRI);
|
|
@@ -336,6 +349,7 @@ static struct {
|
|
|
uint8_t idx, nr_idx;
|
|
|
bool_t packet_ready;
|
|
|
bool_t write_finished;
|
|
|
+ bool_t terminate_at_index;
|
|
|
unsigned int packet_len;
|
|
|
int ticks_since_index;
|
|
|
uint32_t ticks_since_flux;
|
|
@@ -627,7 +641,7 @@ static void floppy_process_write_packet(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void floppy_write_prep(void)
|
|
|
+static void floppy_write_prep(struct gw_write_flux *wf)
|
|
|
{
|
|
|
/* Initialise DMA ring indexes (consumer index is implicit). */
|
|
|
dma_wdata.cndtr = ARRAY_SIZE(dma.buf);
|
|
@@ -645,6 +659,9 @@ static void floppy_write_prep(void)
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
static void floppy_write_wait_data(void)
|
|
@@ -727,6 +744,10 @@ static void floppy_write(void)
|
|
|
floppy_process_write_packet();
|
|
|
wdata_decode_flux();
|
|
|
|
|
|
+ /* Early termination on index pulse? */
|
|
|
+ if (rw.terminate_at_index && (index.count != 0))
|
|
|
+ goto terminate;
|
|
|
+
|
|
|
if (!rw.write_finished) {
|
|
|
floppy_write_check_underflow();
|
|
|
return;
|
|
@@ -735,15 +756,16 @@ static void floppy_write(void)
|
|
|
/* Wait for DMA ring to drain. */
|
|
|
todo = ~0;
|
|
|
do {
|
|
|
- /* Early termination on index pulse? */
|
|
|
-// if (wr->terminate_at_index && (index.count != index_count))
|
|
|
-// goto out;
|
|
|
+ /* Check for early termination on index pulse. */
|
|
|
+ if (rw.terminate_at_index && (index.count != 0))
|
|
|
+ goto terminate;
|
|
|
/* Check progress of draining the DMA ring. */
|
|
|
prev_todo = todo;
|
|
|
dmacons = ARRAY_SIZE(dma.buf) - dma_wdata.cndtr;
|
|
|
todo = (dma.prod - dmacons) & (ARRAY_SIZE(dma.buf) - 1);
|
|
|
} while ((todo != 0) && (todo <= prev_todo));
|
|
|
|
|
|
+terminate:
|
|
|
floppy_flux_end();
|
|
|
floppy_state = ST_write_flux_drain;
|
|
|
}
|
|
@@ -766,6 +788,13 @@ static void floppy_write_drain(void)
|
|
|
floppy_state = ST_command_wait;
|
|
|
floppy_end_command(u_buf, 1);
|
|
|
drive_deselect();
|
|
|
+
|
|
|
+ /* Reset INDEX handling. */
|
|
|
+ IRQ_global_disable();
|
|
|
+ index.delay = 0;
|
|
|
+ IRQx_clear_pending(irq_index_delay);
|
|
|
+ timer_cancel(&index.delay_timer);
|
|
|
+ IRQ_global_enable();
|
|
|
}
|
|
|
|
|
|
static void process_command(void)
|
|
@@ -828,8 +857,10 @@ static void process_command(void)
|
|
|
break;
|
|
|
}
|
|
|
case CMD_WRITE_FLUX: {
|
|
|
- if (len != 2) goto bad_command;
|
|
|
- floppy_write_prep();
|
|
|
+ struct gw_write_flux wf = { 0 };
|
|
|
+ if ((len < 2) || (len > (2 + sizeof(wf)))) goto bad_command;
|
|
|
+ memcpy(&wf, &u_buf[2], len-2);
|
|
|
+ floppy_write_prep(&wf);
|
|
|
break;
|
|
|
}
|
|
|
case CMD_GET_FLUX_STATUS: {
|
|
@@ -936,13 +967,29 @@ const struct usb_class_ops usb_cdc_acm_ops = {
|
|
|
* INTERRUPT HANDLERS
|
|
|
*/
|
|
|
|
|
|
+static void index_delay_timer(void *unused)
|
|
|
+{
|
|
|
+ index.count++;
|
|
|
+}
|
|
|
+
|
|
|
+static void IRQ_INDEX_delay(void)
|
|
|
+{
|
|
|
+ timer_set(&index.delay_timer, index.timestamp + index.delay);
|
|
|
+}
|
|
|
+
|
|
|
static void IRQ_INDEX_changed(void)
|
|
|
{
|
|
|
/* Clear INDEX-changed flag. */
|
|
|
exti->pr = m(pin_index);
|
|
|
|
|
|
- index.count++;
|
|
|
index.rdata_cnt = tim_rdata->cnt;
|
|
|
+ index.timestamp = time_now();
|
|
|
+
|
|
|
+ if (index.delay != 0) {
|
|
|
+ IRQx_set_pending(irq_index_delay);
|
|
|
+ } else {
|
|
|
+ index.count++;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/*
|