Viewing file: common.c (15.65 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* * Copyright (C) Eicon Technology Corporation, 2000. * * Eicon File Revision : 1.15 * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */
#include "eicon.h" #include "sys.h" #include "idi.h" #include "constant.h" #include "divas.h" #include "pc.h" #include "pr_pc.h"
#include "uxio.h"
#define DIVAS_LOAD_CMD 0x02 #define DIVAS_START_CMD 0x03 #define DIVAS_IRQ_RESET 0xC18 #define DIVAS_IRQ_RESET_VAL 0xFE
#define TEST_INT_DIVAS 0x11 #define TEST_INT_DIVAS_BRI 0x12 #define TEST_INT_DIVAS_Q 0x13
#define DIVAS_RESET 0x81 #define DIVAS_LED1 0x04 #define DIVAS_LED2 0x08 #define DIVAS_LED3 0x20 #define DIVAS_LED4 0x40
#define DIVAS_SIGNATURE 0x4447
#define MP_PROTOCOL_ADDR 0xA0011000
#define PLX_IOBASE 0 #define DIVAS_IOBASE 1
typedef struct { dword cmd; dword addr; dword len; dword err; dword live; dword reserved[(0x1020>>2)-6]; dword signature; byte data[1]; } diva_server_boot_t;
int DivasCardNext; card_t DivasCards[MAX_CARDS];
dia_config_t *DivasConfig(card_t *, dia_config_t *);
static DESCRIPTOR DIDD_Table[32];
void DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength ) { memset(table, 0, tablelength);
if (tablelength > sizeof(DIDD_Table)) tablelength = sizeof(DIDD_Table);
if(tablelength % sizeof(DESCRIPTOR)) { tablelength /= sizeof(DESCRIPTOR); tablelength *= sizeof(DESCRIPTOR); }
if (tablelength > 0) memcpy((void *)table, (void *)DIDD_Table, tablelength);
return; }
void DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength) { if (tablelength > sizeof(DIDD_Table)) tablelength = sizeof(DIDD_Table);
memcpy((void *)DIDD_Table, (void *)table, tablelength);
return; }
static void init_idi_tab(void) { DESCRIPTOR d[32];
memset(d, 0, sizeof(d));
d[0].type = IDI_DIMAINT; /* identify the DIMAINT entry */ d[0].channels = 0; /* zero channels associated with dimaint*/ d[0].features = 0; /* no features associated with dimaint */ d[0].request = (IDI_CALL) DivasPrintf; DIVA_DIDD_Write(d, sizeof(d));
return; }
/* * I/O routines for memory mapped cards */
byte mem_in(ADAPTER *a, void *adr) { card_t *card = a->io; unsigned char *b, *m; byte value;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemIn(card->hw, m);
UxCardMemDetach(card->hw, b);
return value; }
word mem_inw(ADAPTER *a, void *adr) { card_t *card = a->io; unsigned char *b, *m; word value;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemInW(card->hw, m);
UxCardMemDetach(card->hw, b);
return value; }
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length) { card_t *card = a->io; unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemInBuffer(card->hw, m, P, length);
UxCardMemDetach(card->hw, b);
return; }
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e) { card_t *card = a->io; unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (dword) &RBuffer->length; card->RBuffer.length = UxCardMemInW(card->hw, m);
m = b; m += (dword) &RBuffer->P; UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
e->RBuffer = (DBUFFER *) &card->RBuffer;
UxCardMemDetach(card->hw, b);
return; }
void mem_out(ADAPTER *a, void *adr, byte data) { card_t *card = a->io; unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOut(card->hw, m, data);
UxCardMemDetach(card->hw, b);
return; }
void mem_outw(ADAPTER *a, void *adr, word data) { card_t *card = a->io; unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOutW(card->hw, m, data);
UxCardMemDetach(card->hw, b);
return; }
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length) { card_t *card = a->io; unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOutBuffer(card->hw, m, P, length);
UxCardMemDetach(card->hw, b);
return; }
void mem_inc(ADAPTER *a, void *adr) { word value; card_t *card = a->io; unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemInW(card->hw, m); value++; UxCardMemOutW(card->hw, m, value);
UxCardMemDetach(card->hw, b);
return; }
/* * I/O routines for I/O mapped cards */
byte io_in(ADAPTER *a, void *adr) { card_t *card = a->io; byte value; byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoIn(card->hw, DivasIOBase, adr);
UxCardMemDetach(card->hw, DivasIOBase);
return value; }
word io_inw(ADAPTER *a, void *adr) { card_t *card = a->io; word value; byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoInW(card->hw, DivasIOBase, adr);
UxCardMemDetach(card->hw, DivasIOBase);
return value; }
void io_in_buffer(ADAPTER *a, void *adr, void *P, word length) { card_t *card = a->io; byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
UxCardMemDetach(card->hw, DivasIOBase);
return; }
void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e) { card_t *card = a->io; byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
UxCardMemDetach(card->hw, DivasIOBase);
e->RBuffer = (DBUFFER *) &card->RBuffer;
return; }
void io_out(ADAPTER *a, void *adr, byte data) { card_t *card = a->io; byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOut(card->hw, DivasIOBase, adr, data);
UxCardMemDetach(card->hw, DivasIOBase);
return; }
void io_outw(ADAPTER *a, void *adr, word data) { card_t *card = a->io; byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutW(card->hw, DivasIOBase, adr, data);
UxCardMemDetach(card->hw, DivasIOBase);
return; }
void io_out_buffer(ADAPTER *a, void *adr, void *P, word length) { card_t *card = a->io; byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
UxCardMemDetach(card->hw, DivasIOBase);
return; }
void io_inc(ADAPTER *a, void *adr) { word value; card_t *card = a->io; byte *DivasIOBase;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoInW(card->hw, DivasIOBase, adr); value++;
UxCardIoOutW(card->hw, DivasIOBase, adr, value);
UxCardMemDetach(card->hw, DivasIOBase);
return; }
static void test_int(card_t *card)
{ byte *shared, *DivasIOBase;
switch (card->test_int_pend) { case TEST_INT_DIVAS: DPRINTF(("divas: test interrupt pending")); shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
if (UxCardMemIn(card->hw, &shared[0x3FE])) { UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->RcOutput), 0); UxCardMemDetach(card->hw, shared); (*card->reset_int)(card); shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); UxCardMemOut(card->hw, &shared[0x3FE], 0); DPRINTF(("divas: test interrupt cleared")); }
UxCardMemDetach(card->hw, shared);
card->test_int_pend = 0; break;
case TEST_INT_DIVAS_BRI: DPRINTF(("divas: BRI test interrupt pending")); (*card->reset_int)(card); DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE); UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0); UxCardMemDetach(card->hw, DivasIOBase); DPRINTF(("divas: test interrupt cleared")); card->test_int_pend = 0; break;
case TEST_INT_DIVAS_Q: DPRINTF(("divas: 4BRI test interrupt pending")); (*card->reset_int)(card); card->test_int_pend = 0; break;
default: DPRINTF(("divas: unknown test interrupt pending")); return; } return; }
void card_isr (void *dev_id) { card_t *card = (card_t *) dev_id; ADAPTER *a = &card->a; int ipl;
if (card->test_int_pend) { ipl = UxCardLock(card->hw); card->int_pend=0; test_int(card); UxCardUnlock(card->hw,ipl); return; } if(card->card_isr) { (*(card->card_isr))(card); } else { ipl = UxCardLock(card->hw); if ((card->test_int)(a)) { (card->reset_int)(card); } UxCardUnlock(card->hw,ipl); }
}
int DivasCardNew(dia_card_t *card_info) { card_t *card; static boolean_t first_call = TRUE; boolean_t NeedISRandReset = FALSE;
DPRINTF(("divas: new card "));
if (first_call) { first_call = FALSE; init_idi_tab(); }
DivasConfigGet(card_info); if (DivasCardNext == DIM(DivasCards)) { KDPRINTF((KERN_WARNING "Divas: no space available for new card")); return -1; }
card = &DivasCards[DivasCardNext];
card->state = DIA_UNKNOWN;
card->cfg = *card_info;
card->a.io = card;
if (UxCardHandleGet(&card->hw, card_info)) { KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card")); return -1; }
if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B) { DivasBriPatch(card); card_info->io_base = card->cfg.io_base; }
switch (card_info->card_type) { case DIA_CARD_TYPE_DIVA_SERVER: if (DivasPriInit(card, card_info)) { return -1; } NeedISRandReset = TRUE; break;
case DIA_CARD_TYPE_DIVA_SERVER_B: if (DivasBriInit(card, card_info)) { return -1; } NeedISRandReset = TRUE; break;
case DIA_CARD_TYPE_DIVA_SERVER_Q: if (Divas4BriInit(card, card_info)) { return -1; }
if (card_info->name[6] == '0') { NeedISRandReset = TRUE; } else // Need to set paramater for ISR anyway { card->hw->user_isr_arg = card; card->hw->user_isr = card_isr; } break;
default: KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type)); return -1; }
if (NeedISRandReset) { if (UxIsrInstall(card->hw, card_isr, card)) { KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq)); UxCardHandleFree(card->hw); return -1; }
if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q) { if ((*card->card_reset)(card)) { KDPRINTF((KERN_WARNING "Divas: Adapter reset failed")); return -1; } card->state = DIA_RESET; }
NeedISRandReset = FALSE; }
DivasCardNext++;
return 0; }
void *get_card(int card_id) { int i;
for (i=0; i < DivasCardNext; i++) { if (DivasCards[i].cfg.card_id == card_id) { return(&DivasCards[i]); } }
DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
return NULL; }
int DivasCardConfig(dia_config_t *config) { card_t *card; int status;
DPRINTF(("divas: configuring card"));
card = get_card(config->card_id); if (!card) { return -1; }
config = DivasConfig(card, config);
status = (*card->card_config)(card, config);
if (!status) { card->state = DIA_CONFIGURED; } return status; }
int DivasCardLoad(dia_load_t *load) { card_t *card; int status;
card = get_card(load->card_id); if (!card) { return -1; }
if (card->state == DIA_RUNNING) { (*card->card_reset)(card); }
status = (*card->card_load)(card, load); if (!status) { card->state = DIA_LOADED; } return status; }
static int idi_register(card_t *card, byte channels) { DESCRIPTOR d[32]; int length, num_entities;
DPRINTF(("divas: registering card with IDI"));
num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES; card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
if (!card->e_tbl) { KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available")); return -1; }
memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities); card->e_max = num_entities;
DIVA_DIDD_Read(d, sizeof(d));
for(length=0; length < DIM(d); length++) if (d[length].type == 0) break;
if (length >= DIM(d)) { KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full")); return -1; }
switch (card->cfg.card_type) { case DIA_CARD_TYPE_DIVA_SERVER: d[length].type = IDI_ADAPTER_PR; /* d[length].serial = card->serial_no; */ break;
case DIA_CARD_TYPE_DIVA_SERVER_B: d[length].type = IDI_ADAPTER_MAESTRA; /* d[length].serial = card->serial_no; */ break;
// 4BRI is treated as 4 BRI adapters case DIA_CARD_TYPE_DIVA_SERVER_Q: d[length].type = IDI_ADAPTER_MAESTRA; /* d[length].serial = card->cfg.serial; */ }
d[length].features = 0; d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
if ( card->hw->features & PROTCAP_MANIF ) { d[length].features |= DI_MANAGE ; } if ( card->hw->features & PROTCAP_V_42 ) { d[length].features |= DI_V_42 ; } if ( card->hw->features & PROTCAP_EXTD_FAX ) { d[length].features |= DI_EXTD_FAX ; }
d[length].channels = channels; d[length].request = DivasIdiRequest[card - DivasCards];
length++;
DIVA_DIDD_Write(d, sizeof(d));
return 0; }
int DivasCardStart(int card_id) { card_t *card; byte channels; int status;
DPRINTF(("divas: starting card"));
card = get_card(card_id); if (!card) { return -1; }
status = (*card->card_start)(card, &channels); if (status) { return status; }
/* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */ if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q) { int i; card_t *FourBRISlave;
for (i=3; i >= 0; i--) { FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */ if (FourBRISlave) { idi_register(FourBRISlave, 2); FourBRISlave->state = DIA_RUNNING; } } card->serial_no = card->cfg.serial;
DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels", card_id - 3, card->serial_no, (int) channels)); } else { status = idi_register(card, channels); if (!status) { card->state = DIA_RUNNING; DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels", card_id, card->serial_no, (int) channels)); } }
return status; }
int DivasGetMem(mem_block_t *mem_block) { card_t *card; word card_id = mem_block->card_id;
card = get_card(card_id); if (!card) { return 0; }
return (*card->card_mem_get)(card, mem_block); }
/* * Deleyed Procedure Call for handling interrupts from card */
void DivaDoCardDpc(card_t *card) { ADAPTER *a;
a = &card->a;
if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1) { return; }
do{ if((*(card->test_int))(a)) { (*(card->dpc))(a); (*(card->clear_int))(a); } (*(card->out))(a); }while(UxInterlockedDecrement(card->hw, &card->dpc_reentered)); }
void DivasDoDpc(void *pData) { card_t *card = DivasCards; int i = DivasCardNext; while(i--) { if (card->state == DIA_RUNNING) DivaDoCardDpc(card); card++; } }
void DivasDoRequestDpc(void *pData) { DivasDoDpc(pData); }
/* * DivasGetNum * Returns the number of active adapters */
int DivasGetNum(void) { return(DivasCardNext); }
/* * DivasGetList * Returns a list of active adapters */ int DivasGetList(dia_card_list_t *card_list) { int i;
memset(card_list, 0, sizeof(dia_card_list_t));
for(i = 0; i < DivasCardNext; i++) { card_list->card_type = DivasCards[i].cfg.card_type; card_list->card_slot = DivasCards[i].cfg.slot; card_list->state = DivasCards[i].state; card_list++; }
return 0;
}
/* * control logging for specified card */
void DivasLog(dia_log_t *log) { card_t *card;
card = get_card(log->card_id); if (!card) { return; }
card->log_types = log->log_types;
return; }
|