summaryrefslogtreecommitdiff
path: root/hal/phy/src/phy.c
diff options
context:
space:
mode:
authorschodet2008-02-14 16:14:03 +0000
committerschodet2008-02-14 16:14:03 +0000
commitb96644e08a2652ba5858821950674236f86a84cc (patch)
tree37e1489555434e11678a1e687d1ac90c991e1d33 /hal/phy/src/phy.c
parent58ad9e0801f128f22725389394c5d6bb891d3323 (diff)
* hal/phy:
- first HAL Phy for real hardware. git-svn-id: svn+ssh://pessac/svn/cesar/trunk@1416 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'hal/phy/src/phy.c')
-rw-r--r--hal/phy/src/phy.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/hal/phy/src/phy.c b/hal/phy/src/phy.c
new file mode 100644
index 0000000000..2e5fa8093c
--- /dev/null
+++ b/hal/phy/src/phy.c
@@ -0,0 +1,228 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/phy/src/phy.c
+ * \brief HAL Phy general functions.
+ * \ingroup hal_phy
+ */
+#include "common/std.h"
+
+#include "hal/phy/phy.h"
+
+#include "inc/context.h"
+#include "inc/regs.h"
+
+#include "hal/leon/itc2.h"
+
+/** TM DMA descriptor. */
+struct phy_tmdma_desc_t
+{
+ /** Pointer to next descriptor. */
+ struct blk_t *next;
+ /** Pointer to data. */
+ u8 *data;
+ BITFIELDS_WORD (
+ /** Transfer configuration: size. */
+ u32 size_words:8;,
+ /** Transfer configuration: memory index. */
+ u32 mem_index:3;,
+ /** Transfer configuration: last. */
+ u32 last:1;,
+ u32 :4;,
+ /** Transfer configuration: local start address in memory. */
+ u32 local_start_addr:16;)
+};
+typedef struct phy_tmdma_desc_t phy_tmdma_desc_t;
+
+/** TM DMA memory indexes. */
+enum phy_tmdma_mem_index_t
+{
+ PHY_TMDMA_MEM_TONEMASK = 0,
+ PHY_TMDMA_MEM_AMPLITUDE_MAP = 1,
+ PHY_TMDMA_MEM_ADAPT_TABLE = 2,
+ PHY_TMDMA_MEM_TONEMAP_0 = 3,
+ PHY_TMDMA_MEM_TONEMAP_1 = 4,
+};
+
+/** Global Phy context. */
+static phy_t phy_global;
+
+/**
+ * Interrupt handler.
+ * \param vector interrupt vector number
+ * \param data phy context
+ * \return status
+ */
+static cyg_uint32
+phy_isr (cyg_vector_t vector, cyg_addrword_t data)
+{
+ phy_t *ctx = (phy_t *) data;
+ dbg_assert (ctx);
+ bool call_dsr;
+ dbg_assert (BF_GET (LEON_ITC2_STATUS__IP, LEON_ITC2_STATUS));
+ uint it = BF_GET (LEON_ITC2_STATUS__IRL, LEON_ITC2_STATUS);
+ if (it == LEON_ITC2_IT__RESYS)
+ {
+ u32 rx_date = PHY_PRATIC_STA_LAST_RECEIVED_FRAME_DATE
+ - BF_GET (PHY_DSPSS_RESYS_DETECTION_OFFSET__PREAMBLE,
+ PHY_DSPSS_RESYS_DETECTION_OFFSET);
+ bool fc_ok = (PHY_DSPSS_RX_FC_AV_STATUS &
+ PHY_DSPSS_RX_FC_AV_STATUS__OK_MASK)
+ == PHY_DSPSS_RX_FC_AV_STATUS__OK_MASK;
+ if (fc_ok)
+ {
+ u32 fc_av[4];
+ fc_av[0] = PHY_DSPSS_RX_FC_AV_0;
+ fc_av[1] = PHY_DSPSS_RX_FC_AV_1;
+ fc_av[2] = PHY_DSPSS_RX_FC_AV_2;
+ fc_av[3] = PHY_DSPSS_RX_FC_AV_3;
+ call_dsr = ctx->rx_fc_cb (ctx->user_data, rx_date, fc_av);
+ }
+ else
+ call_dsr = ctx->rx_fc_cb (ctx->user_data, rx_date, NULL);
+ }
+ else if (it == LEON_ITC2_IT__PB_DMA_END
+ || it == LEON_ITC2_IT__PB_DMA_ERROR)
+ {
+ u32 status_word = PHY_PBDMA_STATUS_ERROR;
+ call_dsr = ctx->pbdma_cb (ctx->user_data, status_word);
+ }
+ else if (it == LEON_ITC2_IT__PRATIC_ACCESS)
+ {
+ call_dsr = ctx->access_cb (ctx->user_data);
+ }
+ else if (it == LEON_ITC2_IT__PRATIC_ACCESS_CONF)
+ {
+ call_dsr = ctx->access_conf_cb (ctx->user_data);
+ }
+ else if (it == LEON_ITC2_IT__PRATIC_INTERRUPT)
+ {
+ call_dsr = ctx->extra_timer_cb (ctx->user_data);
+ }
+ else
+ {
+ dbg_assert (0);
+ }
+ return call_dsr ? CYG_ISR_CALL_DSR : CYG_ISR_HANDLED;
+}
+
+/**
+ * DSR handler.
+ * \param vector interrupt vector number
+ * \param count number of time DSR was requested
+ * \param data phy context
+ * \return status
+ */
+static void
+phy_dsr (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ phy_t *ctx = (phy_t *) data;
+ dbg_assert (ctx);
+ ctx->deferred_cb (ctx->user_data);
+}
+
+phy_t *
+phy_init (void *user_data, phy_rx_fc_cb_t rx_fc_cb, phy_access_cb_t access_cb,
+ phy_access_conf_cb_t access_conf_cb, phy_pbdma_cb_t pbdma_cb,
+ phy_deferred_cb_t deferred_cb)
+{
+ /* Initialise context. */
+ phy_t *ctx = &phy_global;
+ ctx->user_data = user_data;
+ ctx->rx_fc_cb = rx_fc_cb;
+ ctx->access_cb = access_cb;
+ ctx->access_conf_cb = access_conf_cb;
+ ctx->pbdma_cb = pbdma_cb;
+ ctx->deferred_cb = deferred_cb;
+ ctx->extra_timer_user_data = NULL;
+ ctx->extra_timer_cb = NULL;
+ /* Attach interrupt. */
+ cyg_drv_interrupt_create (LEON_ITC2_HIGH_PRIORITY_ITC1_IT,
+ LEON_ITC2_HIGH_PRIORITY_ITC1_IT_PRIORITY,
+ (cyg_addrword_t) ctx,
+ phy_isr,
+ phy_dsr,
+ &ctx->interrupt_handle,
+ &ctx->interrupt_context);
+ cyg_drv_interrupt_attach (ctx->interrupt_handle);
+ cyg_drv_interrupt_unmask (LEON_ITC2_HIGH_PRIORITY_ITC1_IT);
+ /* Initialise hardware. */
+ /* TODO */
+ /* Done. */
+ return ctx;
+}
+
+void
+phy_set_tonemask (phy_t *ctx, u8 *tonemask, uint carrier_nb)
+{
+ dbg_assert (ctx);
+ dbg_assert_ptr (tonemask);
+ dbg_assert (((u32) tonemask & 0x3) == 0);
+ /* Send new tonemask. */
+ phy_tmdma_desc_t desc;
+ desc.next = NULL;
+ desc.data = (u32 *) tonemask;
+ desc.size_words = (PHY_CARRIER_NB + 31) / 32;
+ desc.mem_index = PHY_TMDMA_MEM_TONEMASK;
+ desc.last = 1;
+ desc.local_start_addr = 0;
+ PHY_DSPSS_TMD_DESC_ADDR = (u32) &desc;
+ dbg_assert (!(PHY_DSPSS_TMD_CTRL & BF_MASK (PHY_DSPSS_TMD_CTRL__BUSY)));
+ PHY_PRATIC_IMMEDIATE_ACTION = PHY_PRATIC_ACTION__TMD_START;
+ /* Set AV parameters. */
+ PHY_DSPSS_HPAV_MASK = BF_SHIFT (PHY_DSPSS_HPAV_MASK__NB_CARRIER,
+ carrier_nb);
+ /* Set HP 1.0 parameters. */
+ /* TODO */
+ /* Set ROBO parameters. */
+ /* TODO */
+}
+
+void
+phy_uninit (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ /* Detach interrupt. */
+ cyg_drv_interrupt_unmask (LEON_ITC2_HIGH_PRIORITY_ITC1_IT);
+ cyg_drv_interrupt_detach (ctx->interrupt_handle);
+ cyg_drv_interrupt_delete (ctx->interrupt_handle);
+}
+
+void
+phy_reset (phy_t *ctx)
+{
+ dbg_assert (ctx);
+ /* TODO */
+}
+
+void
+phy_set_tonemap (phy_t *ctx, uint tonemap_index, blk_t *tonemap)
+{
+ dbg_assert (ctx);
+ dbg_assert (tonemap_index < 2);
+ dbg_assert_ptr (tonemap);
+ dbg_assert_ptr (tonemap->data);
+ dbg_assert_ptr (tonemap->next);
+ dbg_assert_ptr (tonemap->next->data);
+ /* Send new tonemap. */
+ const tm_words = (PHY_CARRIER_NB * 4 + 31) / 32;
+ dbg_assert (tm_words > BLK_SIZE / 4 && tm_words < 2 * BLK_SIZE / 4);
+ phy_tmdma_desc_t *desc = (phy_tmdma_desc_t) tonemap;
+ desc->size_words = BLK_SIZE / 4;
+ desc->mem_index = PHY_TMDMA_MEM_TONEMAP_0 + tonemap_index;
+ desc->last = 0;
+ desc->local_start_addr = 0;
+ desc->next->size_words = tm_words - BLK_SIZE / 4;
+ desc->next->mem_index = PHY_TMDMA_MEM_TONEMAP_0 + tonemap_index;
+ desc->next->last = 1;
+ desc->next->local_start_addr = BLK_SIZE * 2; /* Two cells per byte. */
+ PHY_DSPSS_TMD_DESC_ADDR = (u32) desc;
+ dbg_assert (!(PHY_DSPSS_TMD_CTRL & BF_MASK (PHY_DSPSS_TMD_CTRL__BUSY)));
+ PHY_PRATIC_IMMEDIATE_ACTION = PHY_PRATIC_ACTION__TMD_START;
+}
+