📄 serpkt.c
字号:
/* -*-C-*- * * $Revision: 1.1 $ * $Author: rivimey $ * $Date: 1999/03/11 11:53:45 $ * * 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 "angel.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 */#if DEBUG == 1#define INC_STAT(x) x++#define INC_STAT_BY(x,y) x += (y)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};#else#define INC_STAT(x)#define INC_STAT_BY(x,y)#endif/* 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; /* * 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; INC_STAT(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); INC_STAT(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 */ if ((*status & SER_TX_KICKSTART) != 0) { *status |= SER_TX_DATA; *status &= ~SER_TX_KICKSTART; SerCtrl(devid)->control_tx(devid); 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; LogInfo(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); LogInfo(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 LogInfo(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){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -