Procházet zdrojové kódy

floppy: Split rw state into flux_op, read, write structures.

Keir Fraser před 4 roky
rodič
revize
9f7dfe57ad
1 změnil soubory, kde provedl 76 přidání a 66 odebrání
  1. 76 66
      src/floppy.c

+ 76 - 66
src/floppy.c

@@ -90,6 +90,15 @@ static struct {
     uint8_t data[USB_HS_MPS];
 } usb_packet;
 
+/* Read, write, erase: Shared command state. */
+static struct {
+    union {
+        time_t start; /* read, write: Time at which read/write started. */
+        time_t end;   /* erase: Time at which to end the erasure. */
+    };
+    uint8_t status;
+} flux_op;
+
 static enum {
     ST_inactive,
     ST_command_wait,
@@ -298,22 +307,8 @@ static void floppy_end_command(void *ack, unsigned int ack_len)
  */
 
 static struct {
-    union {
-        time_t start; /* read, write: Time at which read/write started. */
-        time_t end;   /* erase: Time at which to end the erasure. */
-    };
-    uint8_t status;
-    uint8_t idx, nr_idx;
-    bool_t write_finished;
-    bool_t terminate_at_index;
-    uint32_t astable_period;
-    uint32_t ticks;
-    enum {
-        FLUXMODE_idle,    /* generating no flux (awaiting next command) */
-        FLUXMODE_oneshot, /* generating a single flux */
-        FLUXMODE_astable  /* generating a region of oscillating flux */
-    } flux_mode;
-} rw;
+    unsigned int idx, nr_idx;
+} read;
 
 static void _write_28bit(uint32_t x)
 {
@@ -330,7 +325,7 @@ static void rdata_encode_flux(void)
     timcnt_t prev = dma.prev_sample, curr, next;
     uint32_t ticks;
 
-    ASSERT(rw.idx < rw.nr_idx);
+    ASSERT(read.idx < read.nr_idx);
 
     /* We don't want to race the Index IRQ handler. */
     IRQ_global_disable();
@@ -338,10 +333,10 @@ static void rdata_encode_flux(void)
     /* Find out where the DMA engine's producer index has got to. */
     prod = ARRAY_SIZE(dma.buf) - dma_rdata.ndtr;
 
-    if (rw.idx != index.count) {
+    if (read.idx != index.count) {
         /* We have just passed the index mark: Record information about 
          * the just-completed revolution. */
-        rw.idx = index.count;
+        read.idx = index.count;
         ticks = (timcnt_t)(index.rdata_cnt - prev);
         IRQ_global_enable(); /* we're done reading ISR variables */
         u_buf[U_MASK(u_prod++)] = 0xff;
@@ -419,11 +414,13 @@ static uint8_t floppy_read_prep(const struct gw_read_flux *rf)
     tim_rdata->cr1 = TIM_CR1_CEN;
 
     index.count = 0;
+    usb_packet.ready = FALSE;
+
     floppy_state = ST_read_flux;
-    memset(&rw, 0, sizeof(rw));
-    rw.nr_idx = rf->nr_idx;
-    rw.start = time_now();
-    rw.status = ACK_OKAY;
+    flux_op.start = time_now();
+    flux_op.status = ACK_OKAY;
+    memset(&read, 0, sizeof(read));
+    read.nr_idx = rf->nr_idx;
 
     return ACK_OKAY;
 }
@@ -458,23 +455,23 @@ static void floppy_read(void)
             printk("OVERFLOW %u %u %u %u\n", u_cons, u_prod,
                    usb_packet.ready, ep_tx_ready(EP_TX));
             floppy_flux_end();
-            rw.status = ACK_FLUX_OVERFLOW;
+            flux_op.status = ACK_FLUX_OVERFLOW;
             floppy_state = ST_read_flux_drain;
             u_cons = u_prod = avail = 0;
 
-        } else if (rw.idx >= rw.nr_idx) {
+        } else if (read.idx >= read.nr_idx) {
 
             /* Read all requested revolutions. */
             floppy_flux_end();
             floppy_state = ST_read_flux_drain;
 
         } else if ((index.count == 0)
-                   && (time_since(rw.start) > time_ms(2000))) {
+                   && (time_since(flux_op.start) > time_ms(2000))) {
 
             /* Timeout */
             printk("NO INDEX\n");
             floppy_flux_end();
-            rw.status = ACK_NO_INDEX;
+            flux_op.status = ACK_NO_INDEX;
             floppy_state = ST_read_flux_drain;
             u_cons = u_prod = avail = 0;
 
@@ -507,6 +504,18 @@ static void floppy_read(void)
  * WRITE PATH
  */
 
+static struct {
+    bool_t is_finished;
+    bool_t terminate_at_index;
+    uint32_t astable_period;
+    uint32_t ticks;
+    enum {
+        FLUXMODE_idle,    /* generating no flux (awaiting next command) */
+        FLUXMODE_oneshot, /* generating a single flux */
+        FLUXMODE_astable  /* generating a region of oscillating flux */
+    } flux_mode;
+} write;
+
 static uint32_t _read_28bit(void)
 {
     uint32_t x;
@@ -522,23 +531,23 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
 #define MIN_PULSE sample_ns(800)
 
     unsigned int todo = nr;
-    uint32_t x, ticks = rw.ticks;
+    uint32_t x, ticks = write.ticks;
 
     if (todo == 0)
         return 0;
 
-    switch (rw.flux_mode) {
+    switch (write.flux_mode) {
 
     case FLUXMODE_astable: {
         /* Produce flux transitions at the specified period. */
-        uint32_t pulse = rw.astable_period;
+        uint32_t pulse = write.astable_period;
         while (ticks >= pulse) {
             *tbuf++ = pulse - 1;
             ticks -= pulse;
             if (!--todo)
                 goto out;
         }
-        rw.flux_mode = FLUXMODE_idle;
+        write.flux_mode = FLUXMODE_idle;
         break;
     }
 
@@ -562,7 +571,7 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
                 goto out;
         }
 
-        rw.flux_mode = FLUXMODE_idle;
+        write.flux_mode = FLUXMODE_idle;
         break;
 
     case FLUXMODE_idle:
@@ -573,13 +582,13 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
 
     while (u_cons != u_prod) {
 
-        ASSERT(rw.flux_mode == FLUXMODE_idle);
+        ASSERT(write.flux_mode == FLUXMODE_idle);
 
         x = u_buf[U_MASK(u_cons)];
         if (x == 0) {
             /* 0: Terminate */
             u_cons++;
-            rw.write_finished = TRUE;
+            write.is_finished = TRUE;
             goto out;
         } else if (x < 250) {
             /* 1-249: One byte. Time to next flux.*/
@@ -602,15 +611,16 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
             case FLUXOP_SPACE:
                 ticks += _read_28bit();
                 continue;
-            case FLUXOP_ASTABLE:
-                rw.astable_period = _read_28bit();
-                if ((rw.astable_period < MIN_PULSE)
-                    || (rw.astable_period != (timcnt_t)rw.astable_period)) {
+            case FLUXOP_ASTABLE: {
+                uint32_t period = _read_28bit();
+                if ((period < MIN_PULSE) || (period != (timcnt_t)period)) {
                     /* Bad period value: underflow or overflow. */
                     goto error;
                 }
-                rw.flux_mode = FLUXMODE_astable;
+                write.astable_period = period;
+                write.flux_mode = FLUXMODE_astable;
                 goto out;
+            }
             default:
                 /* Invalid opcode */
                 u_cons += 4;
@@ -629,7 +639,7 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
         /* This sample overflows the hardware timer's counter width?
          * Then bail, and we'll split it into chunks. */
         if (ticks != (timcnt_t)ticks) {
-            rw.flux_mode = FLUXMODE_oneshot;
+            write.flux_mode = FLUXMODE_oneshot;
             goto out;
         }
 
@@ -640,12 +650,12 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
     }
 
 out:
-    rw.ticks = ticks;
+    write.ticks = ticks;
     return nr - todo;
 
 error:
     floppy_flux_end();
-    rw.status = ACK_BAD_COMMAND;
+    flux_op.status = ACK_BAD_COMMAND;
     floppy_state = ST_write_flux_drain;
     goto out;
 }
@@ -712,12 +722,13 @@ static uint8_t floppy_write_prep(const struct gw_write_flux *wf)
     dma_wdata.ndtr = ARRAY_SIZE(dma.buf);
     dma.prod = 0;
 
-    floppy_state = ST_write_flux_wait_data;
-    memset(&rw, 0, sizeof(rw));
-    rw.flux_mode = FLUXMODE_idle;
-    rw.status = ACK_OKAY;
+    usb_packet.ready = FALSE;
 
-    rw.terminate_at_index = wf->terminate_at_index;
+    floppy_state = ST_write_flux_wait_data;
+    flux_op.status = ACK_OKAY;
+    memset(&write, 0, sizeof(write));
+    write.flux_mode = FLUXMODE_idle;
+    write.terminate_at_index = wf->terminate_at_index;
 
     return ACK_OKAY;
 }
@@ -729,7 +740,7 @@ static void floppy_write_wait_data(void)
 
     floppy_process_write_packet();
     wdata_decode_flux();
-    if (rw.status != ACK_OKAY)
+    if (flux_op.status != ACK_OKAY)
         return;
 
     /* We don't wait for the massive F7 u_buf[] to fill at Full Speed. */
@@ -738,10 +749,10 @@ static void floppy_write_wait_data(void)
 
     /* Wait for DMA and input buffers to fill, or write stream to end. We must
      * take care because, since we are not yet draining the DMA buffer, the
-     * write stream may end without us noticing and setting rw.write_finished. 
+     * write stream may end without us noticing and setting write.is_finished. 
      * Hence we peek for a NUL byte in the input buffer if it's non-empty. */
     write_finished = ((u_prod == u_cons)
-                      ? rw.write_finished
+                      ? write.is_finished
                       : (u_buf[U_MASK(u_prod-1)] == 0));
     if (((dma.prod != (ARRAY_SIZE(dma.buf)-1)) 
          || ((uint32_t)(u_prod - u_cons) < u_buf_threshold))
@@ -749,7 +760,7 @@ static void floppy_write_wait_data(void)
         return;
 
     floppy_state = ST_write_flux_wait_index;
-    rw.start = time_now();
+    flux_op.start = time_now();
 
     /* Enable DMA only after flux values are generated. */
     dma_wdata_start();
@@ -765,10 +776,10 @@ static void floppy_write_wait_data(void)
 static void floppy_write_wait_index(void)
 {
     if (index.count == 0) {
-        if (time_since(rw.start) > time_ms(2000)) {
+        if (time_since(flux_op.start) > time_ms(2000)) {
             /* Timeout */
             floppy_flux_end();
-            rw.status = ACK_NO_INDEX;
+            flux_op.status = ACK_NO_INDEX;
             floppy_state = ST_write_flux_drain;
         }
         return;
@@ -798,7 +809,7 @@ static void floppy_write_check_underflow(void)
         printk("UNDERFLOW %u %u %u %u\n", u_cons, u_prod,
                usb_packet.ready, ep_rx_ready(EP_RX));
         floppy_flux_end();
-        rw.status = ACK_FLUX_UNDERFLOW;
+        flux_op.status = ACK_FLUX_UNDERFLOW;
         floppy_state = ST_write_flux_drain;
 
     }
@@ -810,14 +821,14 @@ static void floppy_write(void)
 
     floppy_process_write_packet();
     wdata_decode_flux();
-    if (rw.status != ACK_OKAY)
+    if (flux_op.status != ACK_OKAY)
         return;
 
     /* Early termination on index pulse? */
-    if (rw.terminate_at_index && (index.count != 0))
+    if (write.terminate_at_index && (index.count != 0))
         goto terminate;
 
-    if (!rw.write_finished) {
+    if (!write.is_finished) {
         floppy_write_check_underflow();
         return;
     }
@@ -826,7 +837,7 @@ static void floppy_write(void)
     todo = ~0;
     do {
         /* Check for early termination on index pulse. */
-        if (rw.terminate_at_index && (index.count != 0))
+        if (write.terminate_at_index && (index.count != 0))
             goto terminate;
         /* Check progress of draining the DMA ring. */
         prev_todo = todo;
@@ -842,7 +853,7 @@ terminate:
 static void floppy_write_drain(void)
 {
     /* Drain the write stream. */
-    if (!rw.write_finished) {
+    if (!write.is_finished) {
         floppy_process_write_packet();
         (void)_wdata_decode_flux(dma.buf, ARRAY_SIZE(dma.buf));
         return;
@@ -853,7 +864,7 @@ static void floppy_write_drain(void)
         return;
 
     /* ACK with Status byte. */
-    u_buf[0] = rw.status;
+    u_buf[0] = flux_op.status;
     floppy_state = ST_command_wait;
     floppy_end_command(u_buf, 1);
 }
@@ -871,22 +882,21 @@ static uint8_t floppy_erase_prep(const struct gw_erase_flux *ef)
     write_pin(wgate, TRUE);
 
     floppy_state = ST_erase_flux;
-    memset(&rw, 0, sizeof(rw));
-    rw.status = ACK_OKAY;
-    rw.end = time_now() + time_from_samples(ef->erase_ticks);
+    flux_op.status = ACK_OKAY;
+    flux_op.end = time_now() + time_from_samples(ef->erase_ticks);
 
     return ACK_OKAY;
 }
 
 static void floppy_erase(void)
 {
-    if (time_since(rw.end) < 0)
+    if (time_since(flux_op.end) < 0)
         return;
 
     write_pin(wgate, FALSE);
 
     /* ACK with Status byte. */
-    u_buf[0] = rw.status;
+    u_buf[0] = flux_op.status;
     floppy_state = ST_command_wait;
     floppy_end_command(u_buf, 1);
 }
@@ -1136,7 +1146,7 @@ static void process_command(void)
     case CMD_GET_FLUX_STATUS: {
         if (len != 2)
             goto bad_command;
-        u_buf[1] = rw.status;
+        u_buf[1] = flux_op.status;
         goto out;
     }
     case CMD_SELECT: {