📄 serpkt.c
字号:
/* -*-C-*- * * $Revision: 1.6.6.7 $ * $Author: rivimey $ * $Date: 1998/03/21 22:54:10 $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * * Project: ANGEL * * Title: High-level packet-based device driver for serial (or similar) * devices. Interfaces to low-level drivers via serring.h. */#include "devdriv.h" /* device driver support */#include "rxtx.h" /* rx/tx packet engines */#include "logging.h"#include "serring.h"/* General purpose constants, macros, enums, typedefs *//* Publically-accessible globals */static unsigned long spk_rx_numpackets = 0;static unsigned long spk_rx_numbadpackets = 0;static unsigned long spk_rx_numdrops = 0;static unsigned long spk_rx_numbytes = 0;static unsigned long spk_tx_numpackets = 0;static unsigned long spk_tx_numdrops = 0;static unsigned long spk_tx_numbytes = 0;struct StatInfo spk_stat_info[] ={ "Serpkt Stats:\n" " Transmit\n" " NumPackets %4d\n", &spk_tx_numpackets, " NumPackets Dropped %4d\n", &spk_tx_numdrops, " Number of Bytes %4d\n", &spk_tx_numbytes, "\n" " Receive\n" " NumPackets %4d\n", &spk_rx_numpackets, " NumPackets Bad %4d\n", &spk_rx_numbadpackets, " NumPackets Dropped %4d\n", &spk_rx_numdrops, " Number of Bytes %4d\n", &spk_rx_numbytes, NULL, NULL};/* Private globals *//* none *//* * Function: serpkt_fill_tx_ring * Purpose: Fill ups a transmit ring buffer from the Tx engine * * Pre-conditions: Interrupts should be disabled * * Params: * Input: devid device ID of the driver * * In/Out: ring the ring buffer to be filled * * Returns: Nothing */static void serpkt_fill_tx_ring(const DeviceID devid, RingBuffer * const ring){ volatile unsigned int *const status = angel_DeviceStatus + devid; unsigned int eod = *status & SER_TX_EOD; /* not bool -- it's a bitmask */ /* * loop while data left to send and the buffer has space left */ while ((eod == 0) && !ringBufFull(ring)) { te_status tx_status; unsigned char new_ch;// unsigned int s; /* * This task is running as AngelCallback priority so it can * be interrupted. If a heartbeat arrives which needs to write * an acknowledge, the interrupting heartbeat task will never * terminate (because we're busy); the result is deadlock. * * Interim Solution: Don't let the interrupt happen! */ /* s = Angel_EnableInterruptsFromSVC(); */ tx_status = Angel_TxEngine(SerEngine(devid)->tx_packet, SerEngine(devid)->te_state, &new_ch); /* Angel_RestoreInterruptsFromSVC(s); */ switch (tx_status) { case TS_DONE_PKT: eod = TRUE; spk_tx_numpackets++; /* and FALL THROUGH TO */ case TS_IN_PKT:#if DEBUG == 1 { static int count = 0; LogInfo(LOG_WIRE, (">%02X ", new_ch)); if (++count > 16) { LogInfo(LOG_WIRE, ("\n")); count = 0; } }#endif ringBufPutChar(ring, new_ch); spk_tx_numbytes++; break; case TS_IDLE: LogWarning(LOG_SERPKT, ( "TS_IDLE in fill_ring\n")); break; default: LogError(LOG_SERPKT, ( "Unknown status in fill_ring\n")); break; } } if (eod) *status |= SER_TX_EOD; /* * if ring buffer was empty when we started filling it, then * we need to kick start the first character */ #ifdef NEVER if ((*status & SER_TX_KICKSTART) != 0) { *status |= SER_TX_DATA; *status &= ~SER_TX_KICKSTART; SerCtrl(devid)->control_tx(devid); SerCtrl(devid)->kick_start(devid); }#endif SerCtrl(devid)->kick_start(devid);}/* * Function: serpkt_AsyncWrite * Purpose: Entry point for asynchronous writes to the serial device. * See documentation for angel_DeviceWrite in devdriv.h */DevError serpkt_AsyncWrite(DeviceID devid, p_Buffer buffer, unsigned int length, DevChanID devchan){ struct data_packet *const txp = SerEngine(devid)->tx_packet; RingBuffer *ring = SerCtrl(devid)->tx_ring; txp->len = length; txp->type = devchan; txp->data = buffer; Angel_TxEngineInit(SerEngine(devid)->config, txp, SerEngine(devid)->te_state); /* need to protect this bit */ Angel_EnterSVC(); angel_DeviceStatus[devid] |= SER_TX_KICKSTART; serpkt_fill_tx_ring(devid, ring); Angel_ExitToUSR(); LogInfo(LOG_SERPKT, ( "serpkt_AsyncWrite OK\n")); return DE_OKAY;}/* * Function: serpkt_RegisterRead * Purpose: Entry point for asynchronous reads from the serial device. * See documentation for angel_RegisterRead in devdriv.h */DevError serpkt_RegisterRead(DeviceID devid, DevChanID devchan){ struct data_packet *const rxp = SerEngine(devid)->rx_packet; IGNORE(devchan); LogInfo(LOG_SERPKT, ( "serpkt_RegisterRead\n")); Angel_EnterSVC(); rxp->data = NULL; /* gets set in callback later on */ rxp->type = DC_NUM_CHANNELS; /* invalid */ SerCtrl(devid)->control_rx(devid); Angel_ExitToUSR(); return DE_OKAY;}/* * Function: serpkt_reset * Purpose: Reset a serial port * * Params: * Input: devid device ID of the driver * * Returns: DE_OKAY */static DevError serpkt_reset(const DeviceID devid){ Angel_RxEngineInit(SerEngine(devid)->config, SerEngine(devid)->re_state); /* get low-level control to do the rest */ return SerCtrl(devid)->control(devid, DC_RESET, NULL);}/* * Function: serpkt_rxflow * Purpose: * */static DevError serpkt_rxflow(DeviceID devid, void *v_arg){ int oldarg; int arg = (int)v_arg; LogWarning(LOG_SERPKT, ( "serpkt_rxflow: dev %d arg %x\n", devid, arg)); /* * arg == 0: no packets allowed; * arg > 0: normal processing * arg < 0: allow (-arg) packets (delivered) before disabling flow * Note: delivered packets exclude bad packets! */ if (SerCtrl(devid)->rx_tx_state != NULL) { oldarg = SerCtrl(devid)->rx_tx_state->rx_pkt_flow; SerCtrl(devid)->rx_tx_state->rx_pkt_flow = (int)arg; /* This code is (I think ) only relevant in a system which can * handle multiple tasks... if in minimal angel, therefore, * just ignore it. * * ... I may be wrong! RIC 1/98 */#if !defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0 /* restart the rx engine if it was stopped */ if (arg > 0 && oldarg == 0) { volatile unsigned int *const status = angel_DeviceStatus + devid; if ((*status & SER_RX_QUEUED) == 0) { int s; *status |= SER_RX_QUEUED; /* allow pending ints to be processed... */ s = Angel_EnableInterruptsFromSVC(); Angel_RestoreInterruptsFromSVC(s); LogWarning(LOG_SERPKT, ( "serpkt_rxflow: Queue rx_processing.\n")); /* * This is what is wanted, but it can't be done here and now; * if a packet were delivered as a result, we would end up * reentering code which isn't reentrant! * * SerCtrl(devid)->rx_processing((void*)devid); */ Angel_QueueCallback((angel_CallbackFn)SerCtrl(devid)->rx_processing, TP_AngelWantLock, (void *)devid, 0, 0, 0); } else LogWarning(LOG_SERPKT, ( "serpkt_rxflow: still running\n")); }#endif } /* get low-level control to do the rest */ return SerCtrl(devid)->control(devid, DC_RX_PACKET_FLOW, v_arg);}/* * Function: serpkt_Control * Purpose: Entry point for device control functions * See documentation for angel_DeviceControl in devdriv.h */DevError serpkt_Control(DeviceID devid, DeviceControl op, void *arg){ DevError ret_code; LogInfo(LOG_SERPKT, ( "serpkt_Control: dev %d, op %d arg %x\n", devid, op, arg));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -