]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc
Initial commit of the Deluge T2. Some notes:
[tinyos-2.x.git] / tos / lib / net / Deluge / FlashVolumeManager / FlashVolumeManagerP.nc
diff --git a/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc b/tos/lib/net/Deluge/FlashVolumeManager/FlashVolumeManagerP.nc
new file mode 100644 (file)
index 0000000..f31c716
--- /dev/null
@@ -0,0 +1,209 @@
+/* Copyright (c) 2007 Johns Hopkins University.
+*  All rights reserved.
+*
+*  Permission to use, copy, modify, and distribute this software and its
+*  documentation for any purpose, without fee, and without written
+*  agreement is hereby granted, provided that the above copyright
+*  notice, the (updated) modification history and the author appear in
+*  all copies of this source code.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+*  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+*  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+*  OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+*  THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
+ * @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
+ */
+
+#include "FlashVolumeManager.h"
+
+generic module FlashVolumeManagerP()
+{
+#ifdef DELUGE
+  provides interface Notify<uint8_t>;
+#endif
+  uses {
+    interface BlockRead[uint8_t img_num];
+    interface BlockWrite[uint8_t img_num];
+    interface StorageMap[uint8_t img_num];
+    interface AMSend as SerialAMSender;
+    interface Receive as SerialAMReceiver;
+    interface Leds;
+#ifdef DELUGE
+    interface NetProg;
+    interface Timer<TMilli> as Timer;
+#endif
+  }
+}
+
+implementation
+{
+  // States for keeping track of split-phase events
+  enum {
+    S_IDLE,
+    S_ERASE,
+    S_WRITE,
+    S_READ,
+    S_CRC,
+    S_REPROG,
+  };
+  
+  message_t serialMsg;
+  uint8_t buffer[TOSH_DATA_LENGTH];   // Temporary buffer for "write" operation
+  uint8_t img_num_reboot = 0xFF;       // Image number to reprogram
+  uint8_t state = S_IDLE;              // Manager state for multiplexing "done" events
+  
+  /**
+   * Replies to the PC request with operation results
+   */
+  void sendReply(error_t error, storage_len_t len)
+  {
+    SerialReplyPacket *srpkt = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg);
+    if (error == SUCCESS) {
+      srpkt->error = SERIALMSG_SUCCESS;
+    } else {
+      srpkt->error = SERIALMSG_FAIL;
+    }
+    call SerialAMSender.send(AM_BROADCAST_ADDR, &serialMsg, len);
+  }
+  
+  event void BlockRead.readDone[uint8_t img_num](storage_addr_t addr, 
+                               void* buf, 
+                               storage_len_t len, 
+                               error_t error)
+  {
+    if (state == S_READ) {
+      SerialReplyPacket *serialMsg_payload = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg);
+      if (buf == serialMsg_payload->data) {
+        state = S_IDLE;
+        sendReply(error, len + sizeof(SerialReplyPacket));
+      }
+    }
+  }
+  
+  event void BlockRead.computeCrcDone[uint8_t img_num](storage_addr_t addr, 
+                                     storage_len_t len, 
+                                     uint16_t crc, 
+                                     error_t error)
+  {
+    if (state == S_CRC) {
+      state = S_IDLE;
+      
+      if (error == SUCCESS) {
+        SerialReplyPacket *srpkt = (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg);
+        srpkt->data[1] = crc & 0xFF;
+        srpkt->data[0] = (crc >> 8) & 0xFF;
+      }
+      sendReply(error, 2 + sizeof(SerialReplyPacket));
+    }
+  }
+  
+  event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, 
+                                 void* buf, 
+                                 storage_len_t len, 
+                                 error_t error)
+  {
+    if (state == S_WRITE && buf == buffer) {
+      state = S_IDLE;
+      sendReply(error, sizeof(SerialReplyPacket));
+    }
+  }
+  
+  event void BlockWrite.eraseDone[uint8_t img_num](error_t error)
+  {
+    if (state == S_ERASE) {
+      state = S_IDLE;
+      sendReply(error, sizeof(SerialReplyPacket));
+    }
+  }
+  
+  event void BlockWrite.syncDone[uint8_t img_num](error_t error) {}
+  
+  event void SerialAMSender.sendDone(message_t* msg, error_t error) {}
+  
+  event message_t* SerialAMReceiver.receive(message_t* msg, void* payload, uint8_t len)
+  {
+    error_t error = SUCCESS;
+    SerialReqPacket *srpkt = (SerialReqPacket *)payload;
+    SerialReplyPacket *serialMsg_payload =
+                              (SerialReplyPacket *)call SerialAMSender.getPayload(&serialMsg);
+    
+    switch (srpkt->msg_type) {
+      case SERIALMSG_ERASE:    // === Erases a volume ===
+        state = S_ERASE;
+        error = call BlockWrite.erase[srpkt->img_num]();
+        break;
+      case SERIALMSG_WRITE:    // === Writes to a volume ===
+        state = S_WRITE;
+        memcpy(buffer, srpkt->data, srpkt->len);
+        error = call BlockWrite.write[srpkt->img_num](srpkt->offset,
+                                                      buffer,
+                                                      srpkt->len);
+        break;
+      case SERIALMSG_READ:     // === Reads a portion of a volume ===
+        state = S_READ;
+        error = call BlockRead.read[srpkt->img_num](srpkt->offset,
+                                                    serialMsg_payload->data,
+                                                    srpkt->len);
+        break;
+      case SERIALMSG_CRC:      // === Computes CRC over a portion of a volume ===
+        state = S_CRC;
+        error = call BlockRead.computeCrc[srpkt->img_num](srpkt->offset,
+                                                          srpkt->len, 0);
+        break;
+      case SERIALMSG_ADDR:     // === Gets the physical starting address of a volume ===
+       *(nx_uint32_t*)(&serialMsg_payload->data) =
+                             (uint32_t)call StorageMap.getPhysicalAddress[srpkt->img_num](0);
+       sendReply(SUCCESS, sizeof(SerialReplyPacket) + 4);
+        break;
+#ifdef DELUGE
+      case SERIALMSG_REPROG:   // === Reboots and reprograms ===
+        state = S_REPROG;
+        sendReply(SUCCESS, sizeof(SerialReplyPacket));
+        img_num_reboot = srpkt->img_num;
+       call Timer.startOneShot(1024);
+       break;
+      case SERIALMSG_DISS:     // === Starts disseminating a volume ===
+       signal Notify.notify(srpkt->img_num);   // Notifies Deluge to start disseminate
+       sendReply(SUCCESS, sizeof(SerialReplyPacket));
+       break;
+#endif
+    }
+    
+    // If a split-phase operation fails when being requested, signals the failure now
+    if (error != SUCCESS) {
+      state = S_IDLE;
+      sendReply(error, sizeof(SerialReplyPacket));
+    }
+    
+    return msg;
+  }
+
+#ifdef DELUGE
+  event void Timer.fired()
+  {
+    // Reboots and reprograms
+    call NetProg.programImgAndReboot(img_num_reboot);
+  }
+  
+  command error_t Notify.enable() { return SUCCESS; }
+  command error_t Notify.disable() { return SUCCESS; }
+#endif
+
+  default command error_t BlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
+  default command error_t BlockWrite.erase[uint8_t img_num]() { return FAIL; }
+  default command error_t BlockWrite.sync[uint8_t img_num]() { return FAIL; }
+  default command error_t BlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
+  default command error_t BlockRead.computeCrc[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; }
+
+  default command storage_addr_t StorageMap.getPhysicalAddress[uint8_t img_num](storage_addr_t addr) { return 0; }
+}