📄 serpkt.c
字号:
Angel_EnterSVC(); /* we only implement the special cases here */ switch (op) { case DC_INIT: if (SerCtrl(devid)->rx_tx_state) SerCtrl(devid)->rx_tx_state->rx_pkt_flow = 1; ret_code = SerCtrl(devid)->control(devid, op, arg); break; case DC_RESET: ret_code = serpkt_reset(devid); break; case DC_RX_PACKET_FLOW: ret_code = serpkt_rxflow(devid, arg); break; default: /* all others passed through */ ret_code = SerCtrl(devid)->control(devid, op, arg); break; } Angel_ExitToUSR(); return ret_code;}/* * Function: serpkt_int_rx_processing * Purpose: Deferred Rx processing for interrupt handler * * Params: (via args) * Input: devid device ID of the driver * * Returns: Nothing */void serpkt_int_rx_processing(void *args){ const DeviceID devid = (DeviceID) args; RingBuffer *ring = SerCtrl(devid)->rx_ring; volatile int *rx_flow = &(SerCtrl(devid)->rx_tx_state->rx_pkt_flow); volatile unsigned int *status = angel_DeviceStatus + devid; struct data_packet *rxp = SerEngine(devid)->rx_packet; unsigned int s; ASSERT(devid < DI_NUM_DEVICES, ("devid")); LogInfo(LOG_RX, ("Entry: count = %d\n", ringBufCount(ring))); /* * We need to disable IRQ & FIQ whenever we modify critical data * shared with the interrupt handler */ s = Angel_DisableInterruptsFromSVC(); /* * If there are characters in the rx ring buffer, process them * through the rx engine and take appropriate action. */ while (ringBufNotEmpty(ring)) { re_status rx_eng_status; unsigned char new_ch; unsigned char overrun; /* if we've been stopped, get out*/ if (*rx_flow == 0) { LogWarning(LOG_RX, ("Packet processing postponed; rx_flow == 0, ring->count = %d\n", ringBufCount(ring))); break; } overrun = ringBufIsOvr(ring); if (overrun) { LogWarning(LOG_RX, ("Character Overflow detected, ring->count = %d\n", ringBufCount(ring))); ringBufResetOvr(ring); } new_ch = ringBufGetChar(ring); Angel_RestoreInterruptsFromSVC(s);#if DEBUG == 1 /* don't want 'count' maintained in release versions */ { static int count = 0; LogInfo(LOG_WIRE, ("<%02X ", new_ch)); if (++count > 16) { LogInfo(LOG_WIRE, ("\n")); count = 0; } }#endif rx_eng_status = Angel_RxEngine(new_ch, overrun, rxp, SerEngine(devid)->re_state); switch (rx_eng_status) { case RS_WAIT_PKT: case RS_IN_PKT: /* we've done all we need within the engine */ break; case RS_BAD_PKT: /* tell the channels layer about a bad packet */ spk_rx_numbadpackets++; if (rxp->type < DC_NUM_CHANNELS) { LogWarning(LOG_SERPKT, ( "Bad packet: Chan %d; delivering...\n", rxp->type)); angel_DD_GotPacket(devid, rxp->data, rxp->len, DS_BAD_PACKET, rxp->type); } else { LogWarning(LOG_SERPKT, ( "Bad packet: can't deliver...\n")); /* * we assume that if type is bad, no storage has been * allocated in the engine, so just do this to be safe: */ if (rxp->data != NULL) { LogInfo(LOG_SERPKT, ("Bad packet's data non-null, freeing...")); Angel_BufferRelease(rxp->data); } spk_rx_numdrops++; } /* I think now bad packets shouldn't count towards incrementing the * flow; when the flow is set negative, we are really saying "let this * many _good_ packets through. * * if (*rx_flow < 0) * (*rx_flow)++; */ rxp->data = NULL; rxp->type = DC_NUM_CHANNELS; break; case RS_NO_BUF: LogWarning(LOG_SERPKT, ( "No buffer available: can't deliver...\n")); spk_rx_numdrops++; /* * See msg above. * if (*rx_flow < 0) * (*rx_flow)++; */ /* * We've done all we can do within the engine. Don't * try to deliver this; it can cause havoc with task * priorities and anyway there's little point... ric */ rxp->data = NULL; rxp->type = DC_NUM_CHANNELS; /* invalid */ break; case RS_GOOD_PKT: spk_rx_numbytes += rxp->len; spk_rx_numpackets ++; if (*rx_flow < 0) (*rx_flow)++; LogInfo(LOG_SERPKT, ( "Delivering good packet:\n")); angel_DD_GotPacket(devid, rxp->data, rxp->len, DS_DONE, rxp->type); rxp->data = NULL; rxp->type = DC_NUM_CHANNELS; /* invalid */ break; } s = Angel_DisableInterruptsFromSVC(); /* for next test */ } /* * need to clear the flag to say we have been here */ *status &= ~SER_RX_QUEUED; /* * call rx control to reenable interrupts in case they were disabled */ SerCtrl(devid)->control_rx(devid); /* * remember to reenable interrupts before we leave */ Angel_RestoreInterruptsFromSVC(s); LogInfo(LOG_RX, ("Exit: count = %d\n", ringBufCount(ring)));}/* * Function: serpkt_int_tx_processing * Purpose: Deferred Tx processing for interrupt handler * * Params: (via args) * Input: devid device ID of the driver * * Returns: Nothing */void serpkt_int_tx_processing(void *args){ const DeviceID devid = (DeviceID) args; volatile unsigned int *const status = angel_DeviceStatus + devid; RingBuffer *ring = SerCtrl(devid)->tx_ring; struct data_packet *txp = SerEngine(devid)->tx_packet; unsigned int s; ASSERT(devid < DI_NUM_DEVICES, ("serpkt_int_tx_processing: bad devid %d", devid)); /* * We need to disable IRQ & FIQ whenever we modify critical data * shared with the interrupt handler */ s = Angel_DisableInterruptsFromSVC(); /* * If we are called with SER_TX_EOD set then we need to handle * TX completion callback */ if (((*status & SER_TX_EOD) != 0) && ringBufEmpty(ring)) { *status &= ~SER_TX_EOD; Angel_RestoreInterruptsFromSVC(s); angel_DD_SentPacket(devid, txp->data, txp->len, DS_DONE, txp->type); s = Angel_DisableInterruptsFromSVC(); } /* need to clear the flag to say we have been here */ *status &= ~SER_TX_QUEUED; /* * If there is space in the tx ring buffer, fill it up * as far as possible. */ if ((*status & SER_TX_DATA) != 0) { serpkt_fill_tx_ring(devid, ring); } /* remember to reenable interrupts before we leave */ Angel_RestoreInterruptsFromSVC(s);}/**********************************************************************//* * Function: serpkt_flow_control * Purpose: Flow control handler called by Rx engine when it gets an * XON or XOFF * * Pre-conditions: * * Params: * Input: fc_char the Rx character * * cb_data device ID of the driver * * Returns: Nothing */void serpkt_flow_control(char fc_char, void *cb_data){ const DeviceID devid = (DeviceID) cb_data; volatile unsigned int *const status = angel_DeviceStatus + devid; unsigned int s = Angel_DisableInterruptsFromSVC(); ASSERT(devid < DI_NUM_DEVICES, ("serpkt_flow_control: bad devid %d", devid)); if (fc_char == serial_XON) { *status &= ~SER_TX_CONTROLLED_OFF; SerCtrl(devid)->control_tx(devid); } else if (fc_char == serial_XOFF) { *status |= SER_TX_CONTROLLED_OFF; SerCtrl(devid)->control_tx(devid); } Angel_RestoreInterruptsFromSVC(s);}/* EOF serpkt.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -