static void hfc_upload_fsm_entry( struct hfc_card *card, struct hfc_fsm_entry *entry, struct hfc_fsm_entry *next_entry, int fsm_index) { u8 subch_bits; hfc_debug_card(card, 3, "Seq #%d fifo [%d,%s] <=> chan [%d,%s] ", fsm_index, entry->fifo->hw_index, entry->fifo->direction == RX ? "RX" : "TX", entry->hfc_chan_hwindex, entry->fifo->direction == RX ? "RX" : "TX"); hfc_fsm_select_entry(card, fsm_index); hfc_outb(card, hfc_A_CHANNEL, (entry->fifo->direction == RX ? hfc_A_CHANNEL_V_CH_FDIR_RX : hfc_A_CHANNEL_V_CH_FDIR_TX) | hfc_A_CHANNEL_V_CH_FNUM( entry->hfc_chan_hwindex)); switch (entry->fifo->subchannel_bit_count) { case 1: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_1; break; case 2: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_2; break; case 3: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_3; break; case 4: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_4; break; case 5: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_5; break; case 6: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_6; break; case 7: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_7; break; case 8: subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_8; break; default: WARN_ON(1); subch_bits = hfc_A_SUBCH_CFG_V_BIT_CNT_8; } hfc_outb(card, hfc_A_SUBCH_CFG, subch_bits); if (next_entry) { hfc_outb(card, hfc_A_FIFO_SEQ, (next_entry->fifo->direction == RX ? hfc_A_FIFO_SEQ_V_NEXT_FIFO_DIR_RX : hfc_A_FIFO_SEQ_V_NEXT_FIFO_DIR_TX) | hfc_A_FIFO_SEQ_V_NEXT_FIFO_NUM( next_entry->fifo->hw_index)); hfc_debug_cont(3, "=> fifo [%d,%s]\n", next_entry->fifo->hw_index, next_entry->fifo->direction == RX ? "RX" : "TX"); } else { hfc_outb(card, hfc_A_FIFO_SEQ, hfc_A_FIFO_SEQ_V_SEQ_END); hfc_debug_cont(3, "END!\n"); } }
static void hfc_sys_port_upload_fsm( struct hfc_sys_port *port, struct hfc_fsm_entry *entries, int nentries) { struct hfc_card *card = port->card; int i; // Nothing inserted, let's close the empty list :) if (!nentries) { hfc_fsm_select_entry(card, 0); hfc_outb(card, hfc_A_FIFO_SEQ, hfc_A_FIFO_SEQ_V_SEQ_END); return; } hfc_outb(card, hfc_R_FIRST_FIFO, (entries[0].fifo->direction == RX ? hfc_R_FIRST_FIFO_V_FIRST_FIFO_DIR_RX : hfc_R_FIRST_FIFO_V_FIRST_FIFO_DIR_TX) | hfc_R_FIRST_FIFO_V_FIRST_FIFO_NUM(entries[0].fifo->hw_index)); for (i=0; i<nentries; i++) { if (i < nentries-1) hfc_upload_fsm_entry(card, &entries[i], &entries[i+1], i); else hfc_upload_fsm_entry(card, &entries[i], NULL, i); } hfc_pcm_port_select_slot(card, hfc_R_SLOT_V_SL_NUM(0) | hfc_R_SLOT_V_SL_DIR_TX); hfc_outb(card, hfc_A_SL_CFG, hfc_A_SL_CFG_V_CH_SDIR_TX | hfc_A_SL_CFG_V_CH_NUM(0) | hfc_A_SL_CFG_V_ROUT_OUT_STIO1); hfc_pcm_port_select_slot(card, hfc_R_SLOT_V_SL_NUM(10) | hfc_R_SLOT_V_SL_DIR_RX); hfc_outb(card, hfc_A_SL_CFG, hfc_A_SL_CFG_V_CH_SDIR_RX | hfc_A_SL_CFG_V_CH_NUM(0) | hfc_A_SL_CFG_V_ROUT_IN_STIO1); }
static inline void hfc_fsm_select_entry( struct hfc_card *card, int index) { mb(); hfc_outb(card, hfc_R_FSM_IDX, index); hfc_wait_busy(card); // NOT DOCUMENTED BUT MANDATORY!!!!!!! mb(); }
static int hfc_bert_disable( struct hfc_st_chan *chan) { struct hfc_card *card = chan->port->card; hfc_card_lock(card); if (chan->status == HFC_ST_CHAN_STATUS_OPEN_BERT) { chan->status = HFC_ST_CHAN_STATUS_FREE; hfc_st_port_select(chan->port); hfc_st_port_update_st_ctrl0(chan->port); hfc_st_port_update_st_ctrl2(chan->port); // RX hfc_fifo_select(chan->rx.fifo); hfc_fifo_reset(chan->rx.fifo); hfc_outb(card, hfc_A_CON_HDLC, hfc_A_CON_HDCL_V_IFF| hfc_A_CON_HDCL_V_HDLC_TRP_HDLC| hfc_A_CON_HDCL_V_TRP_IRQ_FIFO_DISABLED| hfc_A_CON_HDCL_V_DATA_FLOW_FIFO_from_ST); hfc_outb(card, hfc_A_IRQ_MSK, 0); // TX hfc_fifo_select(chan->tx.fifo); hfc_fifo_reset(chan->tx.fifo); hfc_outb(card, hfc_A_CON_HDLC, hfc_A_CON_HDCL_V_IFF| hfc_A_CON_HDCL_V_HDLC_TRP_HDLC| hfc_A_CON_HDCL_V_TRP_IRQ_FIFO_DISABLED| hfc_A_CON_HDCL_V_DATA_FLOW_FIFO_to_ST_FIFO_to_PCM); hfc_outb(card, hfc_A_IRQ_MSK, 0); hfc_msg_chan(chan, KERN_INFO, "BERT disabled\n"); } hfc_card_unlock(card); return 0; }
void hfc_fifo_configure( struct hfc_fifo *fifo) { struct hfc_card *card = fifo->card; u8 con_hdlc = 0; if (!fifo->enabled) { hfc_outb(card, hfc_A_CON_HDLC, hfc_A_CON_HDCL_V_HDLC_TRP_HDLC | hfc_A_CON_HDCL_V_TRP_IRQ_FIFO_DISABLED); hfc_outb(card, hfc_A_IRQ_MSK, 0); return; } if (fifo->framer_enabled) { con_hdlc |= hfc_A_CON_HDCL_V_HDLC_TRP_HDLC | hfc_A_CON_HDCL_V_IFF | hfc_A_CON_HDCL_V_TRP_IRQ_FIFO_ENABLED; } else { con_hdlc |= hfc_A_CON_HDCL_V_HDLC_TRP_TRP | hfc_A_CON_HDCL_V_TRP_IRQ_DISABLED; } if (fifo->direction == RX) { // if (fifo->connect_to == HFC_FIFO_CONNECT_TO_ST) con_hdlc |= hfc_A_CON_HDCL_V_DATA_FLOW_FIFO_from_ST; // con_hdlc |= hfc_A_CON_HDCL_V_DATA_FLOW_FIFO_from_PCM; // else // con_hdlc |= hfc_A_CON_HDCL_V_DATA_FLOW_FIFO_from_ST_ST_from_PCM; } else { // if (fifo->connect_to == HFC_FIFO_CONNECT_TO_ST) con_hdlc |= hfc_A_CON_HDCL_V_DATA_FLOW_FIFO_to_ST_FIFO_to_PCM; // else // con_hdlc |= hfc_A_CON_HDCL_V_DATA_FLOW_ST_to_PCM; } hfc_outb(card, hfc_A_CON_HDLC, con_hdlc); hfc_outb(card, hfc_A_IRQ_MSK, hfc_A_IRQ_MSK_V_IRQ); }
void hfc_led_update(struct hfc_led *led) { struct hfc_card *card = led->card; enum hfc_led_color color; u8 out_bit = 0; if (led->flashing_freq && (jiffies % led->flashing_freq) > (led->flashing_freq / 2) && led->flashes != 0) color = led->alt_color; else color = led->color; switch(led->id) { case 0: out_bit = hfc_R_GPIO_OUT1_V_GPIO_OUT8; break; case 1: out_bit = hfc_R_GPIO_OUT1_V_GPIO_OUT9; break; case 2: out_bit = hfc_R_GPIO_OUT1_V_GPIO_OUT10; break; case 3: out_bit = hfc_R_GPIO_OUT1_V_GPIO_OUT11; break; } if (color != HFC_LED_OFF) card->gpio_out &= ~out_bit; else card->gpio_out |= out_bit; hfc_outb(card, hfc_R_GPIO_OUT1, card->gpio_out); if (led->flashing_freq && led->flashes != 0) { led->timer.expires = jiffies + led->flashing_freq / 2; add_timer(&led->timer); } }
static ssize_t hfc_store_sq_bits( struct visdn_chan *visdn_chan, struct visdn_chan_attribute *attr, const char *buf, size_t count) { struct hfc_st_chan *chan = to_st_chan(visdn_chan); struct hfc_st_port *port = chan->port; struct hfc_card *card = port->card; unsigned int value; if (sscanf(buf, "%01x", &value) < 1) return -EINVAL; if (value > 0x0f) return -EINVAL; hfc_card_lock(card); hfc_st_port_select(port); hfc_outb(card, hfc_A_ST_SQ_WR, value); hfc_card_unlock(card); return count; }
static int hfc_bert_enable(struct hfc_st_chan *chan) { struct hfc_card *card = chan->port->card; int err; hfc_card_lock(card); if (chan->status != HFC_ST_CHAN_STATUS_FREE) { err = -EBUSY; goto err_busy; } struct hfc_fifo *fifo_rx; fifo_rx = hfc_allocate_fifo(card, RX); if (!fifo_rx) { err = -ENOMEM; goto err_allocate_fifo_rx; } struct hfc_fifo *fifo_tx; fifo_tx = hfc_allocate_fifo(card, TX); if (!fifo_tx) { err = -ENOMEM; goto err_allocate_fifo_tx; } chan->rx.fifo = fifo_rx; chan->rx.fifo->connected_chan = &chan->rx; chan->rx.fifo->bitrate = chan->visdn_chan.pars.bitrate; chan->rx.fifo->framing = VISDN_CHAN_FRAMING_TRANS; chan->rx.fifo->bit_reversed = FALSE; chan->rx.fifo->connect_to = HFC_FIFO_CONNECT_TO_ST; chan->tx.fifo = fifo_tx; chan->tx.fifo->connected_chan = &chan->tx; chan->tx.fifo->bitrate = chan->visdn_chan.pars.bitrate; chan->tx.fifo->framing = VISDN_CHAN_FRAMING_TRANS; chan->tx.fifo->bit_reversed = FALSE; chan->tx.fifo->connect_to = HFC_FIFO_CONNECT_TO_ST; hfc_upload_fsm(card); // RX hfc_fifo_select(chan->rx.fifo); hfc_fifo_configure(chan->rx.fifo); hfc_fifo_reset(chan->rx.fifo); hfc_outb(card, hfc_A_IRQ_MSK, hfc_A_IRQ_MSK_V_BERT_EN); // TX hfc_fifo_select(chan->tx.fifo); hfc_fifo_configure(chan->tx.fifo); hfc_fifo_reset(chan->tx.fifo); hfc_outb(card, hfc_A_IRQ_MSK, hfc_A_IRQ_MSK_V_BERT_EN); chan->status = HFC_ST_CHAN_STATUS_OPEN_BERT; // Enable the channel in the port hfc_st_port_select(chan->port); hfc_st_port_update_st_ctrl0(chan->port); hfc_st_port_update_st_ctrl1(chan->port); hfc_st_port_update_st_ctrl2(chan->port); hfc_card_unlock(card); hfc_msg_chan(chan, KERN_INFO, "BERT enabled\n"); return 0; hfc_deallocate_fifo(fifo_tx); err_allocate_fifo_tx: hfc_deallocate_fifo(fifo_rx); err_allocate_fifo_rx: err_busy: hfc_card_unlock(card); return err; }