📄 devclnt.c
字号:
/* -*-C-*- * * $Revision: 1.1 $ * $Author: rivimey $ * $Date: 1999/03/11 11:53:36 $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * * Project: ANGEL * * Title: Public client interface to devices */#include "devclnt.h"#include "devdriv.h"#include "logging.h"/* private globals *//* all the read callback info for a device */typedef struct ReadCallbacks{ DevRead_CB_Fn callback; void *cb_data; DevGetBuff_Fn get_buff; void *getb_data;} ReadCallbacks;/* all the callback info for a device */typedef struct DevCallbacks{ DevWrite_CB_Fn write_callback; /* current write */ void *write_cb_data; /* current write */ ReadCallbacks read[DC_NUM_CHANNELS];} DevCallbacks;/* stored callbacks and callback data for each device */static DevCallbacks dev_cb[DI_NUM_DEVICES];/* useful for debugging packets */#if DEBUG == 1static void debug_packet(log_id mod, p_Buffer buffer, unsigned int length){#ifndef NO_LOG_INFO log_dump_buffer(WL_INFO, mod, 16, (char*)buffer, length);#endif}#else#define debug_packet(mod, buff, length)#endifDevError angel_DeviceWrite(DeviceID devID, p_Buffer buff, unsigned length, DevWrite_CB_Fn callback, void *cb_data, DevChanID chanID){#ifdef CHECK_PARAMS if (devID >= DI_NUM_DEVICES) { return DE_NO_DEV; } if (chanID >= DC_NUM_CHANNELS) { return DE_BAD_CHAN; } if (angel_Device[devID]->type != DT_ANGEL) { return DE_BAD_DEV; }#endif Angel_EnterSVC(); if (angel_DeviceStatus[devID] & DEV_WRITE_BUSY) { Angel_ExitToUSR(); return DE_BUSY; } angel_DeviceStatus[devID] |= DEV_WRITE_BUSY; /* cleared by device */ Angel_ExitToUSR(); LogInfo(LOG_DEVCLNT, ("angel_DeviceWrite: devid %d, cb %x, devchan %d\n", devID, callback, chanID)); debug_packet(LOG_DEVCLNT, buff, length); /* Okay, we've passed the checks, let's get on with it */ dev_cb[devID].write_callback = callback; dev_cb[devID].write_cb_data = cb_data; LogInfo(LOG_DEVCLNT, ("angel_DeviceWrite: chaining to device async write.\n")); return angel_Device[devID]->rw.angel.async_write(devID, buff, length, chanID);}DevError angel_DeviceRegisterRead(DeviceID devID, DevRead_CB_Fn callback, void *cb_data, DevGetBuff_Fn get_buff, void *getb_data, DevChanID devchanID){ LogInfo(LOG_DEVCLNT, ("angel_DeviceRegisterRead: devID %d, cb %x, devchan %d\n", devID, callback, devchanID));#ifdef CHECK_PARAMS if (devID >= DI_NUM_DEVICES) return DE_NO_DEV; if (devchanID >= DC_NUM_CHANNELS) return DE_BAD_CHAN; if (angel_Device[devID]->type != DT_ANGEL) return DE_BAD_DEV;#endif Angel_EnterSVC(); if (angel_DeviceStatus[devID] & DEV_READ_BUSY(devchanID)) { Angel_ExitToUSR(); return DE_BUSY; } angel_DeviceStatus[devID] |= DEV_READ_BUSY(devchanID); Angel_ExitToUSR(); /* Okay, we've passed the checks, let's get on with it */ dev_cb[devID].read[devchanID].callback = callback; dev_cb[devID].read[devchanID].cb_data = cb_data; dev_cb[devID].read[devchanID].get_buff = get_buff; dev_cb[devID].read[devchanID].getb_data = getb_data; LogInfo(LOG_DEVCLNT, ("angel_DeviceRegisterRead: calling device register.\n")); return angel_Device[devID]->rw.angel.register_read(devID, devchanID);}/* * Function: angel_DeviceControl * Purpose: * * Params: * Input: * * Returns: . */DevError angel_DeviceControl(DeviceID devID, DeviceControl op, void *arg){ LogInfo(LOG_DEVCLNT, ("angel_DeviceControl: devID %d, op %d, arg %x\n", devID, op, arg));#ifdef CHECK_PARAMS if (devID >= DI_NUM_DEVICES) return DE_NO_DEV;#endif return angel_Device[devID]->control(devID, op, arg);}/* * Function: angel_ControlAll * Purpose: * * Params: * Input: * * Returns: . */static void angel_ControlAll(DeviceControl op, void *arg){ int i; LogInfo(LOG_DEVCLNT, ( "angel_ControlAll: op %d, arg %x\n", op, arg)); for (i = 0; i < DI_NUM_DEVICES; ++i) angel_Device[i]->control(i, op, arg);}/* * Function: angel_ReceiveMode * Purpose: * * Params: * Input: * * Returns: . */void angel_ReceiveMode(DevRecvMode mode){ angel_ControlAll(DC_RECEIVE_MODE, (void *)mode);}/* * Function: angel_ResetDevices * Purpose: * * Params: * Input: * * Returns: . */void angel_ResetDevices(void){ angel_ControlAll(DC_RESET, NULL);}/* * Function: angel_InitialiseDevices * Purpose: To call the device initialise code of all devices * configured under Angel. * * Params: * Input: none * * Returns: none */void angel_InitialiseDevices(void){ int i; LogInfo(LOG_DEVCLNT, ( "angel_InitialiseDevices\n")); Angel_InitChannels(); Angel_InitBuffers(); for (i = 0; i < DI_NUM_DEVICES; ++i) { angel_DeviceStatus[i] = 0; angel_Device[i]->control(i, DC_INIT, NULL); } /* err, thats all? */ LogInfo(LOG_DEVCLNT, ( "angel_InitialiseDevices complete.\n"));}/* * Function: angel_IsAngelDevice * * Purpose: To return TRUE if the device is an Angel Packet device, * FALSE if it is a RAW device. * * Params: * Input: devid - the device ID code associated with the device. * * Returns: bool - TRUE or FALSE. */bool angel_IsAngelDevice(DeviceID devID){ ASSERT(devID < DI_NUM_DEVICES, ("illegal device")); return (angel_Device[devID]->type == DT_ANGEL);}/* * Function: angel_DD_GotPacket * * Purpose: Handle receipt of a packet callback. The routine * is called from the High priority task called from * the device ISR, which is expected to convert the * byte- (or other-) formatted data into packet form. * * Various checks are performed to ensure the call * is correct before indexing the callback array to * find the function which will process the packet. * * The callback task will be queued for later action; * this routine *does* return to the caller. * * Params: * Input: devID - the ID code of device which read the data * buff - the buffer in which the data has been placed * length - the length of the data in the buffer * status - DS_DONE if data considered good, else * data is considered bad (e.g. CRC fail, bad * length). * devchanID - the device channel. typically DC_DBUG * for debug (RDI,etc) data, DC_APPL for * other (application) data. * * Returns: nothing. */void angel_DD_GotPacket(DeviceID devID, p_Buffer buff, unsigned length, DevStatus status, DevChanID devchanID){ LogInfo(LOG_DEVCLNT, ("angel_DD_GotPacket: dev %d, buff %x, len %d, stat %s, " "chan %d, [reason %s]\n", devID, buff, length, status == DS_DONE ? "ok" : "*BAD*", devchanID, log_adpname(*(long*)(buff+4)))); ASSERT(devID < DI_NUM_DEVICES, ("devID bad")); ASSERT(devchanID < DC_NUM_CHANNELS, ("devchanID bad")); ASSERT(dev_cb[devID].read[devchanID].callback != NULL, ("no read callback")); if (buff != NULL && length > 0) debug_packet(LOG_DEVCLNT, buff, length); /* * do the call: "callback(buff, length, status, cb_data);" */ Angel_QueueCallback(dev_cb[devID].read[devchanID].callback, TP_AngelCallBack, (void *)buff, (void *)length, (void *)status, (void *)dev_cb[devID].read[devchanID].cb_data); LogInfo(LOG_DEVCLNT, ("angel_DD_GotPacket: returning\n"));}/* * Function: angel_DD_SentPacket * * Purpose: Handle transmission completion. Called as a result of * the device having pulled all the data from the device * ring buffer (more generally: called when a packet send, * initiated with AsyncWrite, has completed). * * Various checks are performed to ensure the call * is correct before indexing the callback array to * find the function which will process the packet. * * The call is used to initiate further action by the code * sending the data. It must also ensure the device BUSY * flag has been reset, indicating that the device can be * used to send something else. * * The callback task will be queued for later action; * this routine *does* return to the caller. * * Params: * Input: devID - which device * buff - pointer to data * length - how much done * status - success code * devchanID - appl or chan * * Returns: nothing */void angel_DD_SentPacket(DeviceID devID, p_Buffer buff, unsigned length, DevStatus status, DevChanID devchanID){ unsigned int s; angel_TaskQueueItem *tqi; LogInfo(LOG_DEVCLNT, ("angel_DD_SentPacket: dev %d, buff %x, len %d, stat %d, " "chan %d, [reason %s]\n", devID, buff, length, status, devchanID, log_adpname(*(long*)(buff+4)))); ASSERT(devID < DI_NUM_DEVICES, ("devID bad")); ASSERT(devchanID < DC_NUM_CHANNELS, ("devchanID bad")); ASSERT(dev_cb[devID].write_callback != NULL, ("no write callback")); /* * We need to protect this */ s = Angel_DisableInterruptsFromSVC(); angel_DeviceStatus[devID] &= ~DEV_WRITE_BUSY; Angel_RestoreInterruptsFromSVC(s); /* * do the call: "callback(buff, length, status, cb_data);" */ tqi = Angel_QueueCallback(dev_cb[devID].write_callback, TP_AngelCallBack, (void *)buff, (void *)length, (void *)status, (void *)dev_cb[devID].write_cb_data); /* * set priority of this higher than normal: we need this task complete ASAP */ angel_SetPriority(tqi, TaskPriorityOf(TP_AngelCallBack) + 1); LogInfo(LOG_DEVCLNT, ("angel_DD_SentPacket: returning\n"));}/* * Function: angel_DD_GetBuffer * * Purpose: To get a buffer from the Angel buffer pool. This will * usually imply a call to the Angel Buffer management * functions, but the exact implementation is hidden behind * the specified "get_buff" function pointer, which allows * a caller to specify it's own buffer management. * * * Params: * Input: devID - the ID of the device requesting the buffer * devchanID - the device channel; typically DC_DBUG * req_size - the minimum number of bytes buffer space * needed * * Returns: a pointer to the buffer, or NULL if not avaiable. * (no distinction is made between no buffer available, * and no buffer of a sufficient size). */p_Buffer angel_DD_GetBuffer(DeviceID devID, DevChanID devchanID, unsigned req_size){ p_Buffer ret_buffer; LogInfo(LOG_DEVCLNT, ("angel_DD_GetBuffer: dev %d, chanID %d, size %d\n", devID, devchanID, req_size)); ASSERT(devID < DI_NUM_DEVICES, ("devID bad")); ASSERT(devchanID < DC_NUM_CHANNELS, ("devchanID bad")); { struct ReadCallbacks *rcb = &dev_cb[devID].read[devchanID]; if (rcb->get_buff == NULL) { LogError(LOG_DEVCLNT, ( "angel_DD_GetBuffer: No alloc fn! (rcb = %p)\n", rcb)); return NULL; } ret_buffer = rcb->get_buff(req_size, rcb->getb_data); } if (ret_buffer == NULL) LogError(LOG_DEVCLNT, ( "angel_DD_GetBuffer: get_buff returned NULL\n")); else LogInfo(LOG_DEVCLNT, ( "angel_DD_GetBuffer: returning buffer 0x%x\n", ret_buffer)); return ret_buffer;}/* EOF devclnt.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -