Viewing file: bri.c (17.64 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* * Copyright (C) Eicon Technology Corporation, 2000. * * Eicon File Revision : 1.8 * * 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 "divas.h" #include "pc.h" #include "pr_pc.h" #include "dsp_defs.h"
#include "adapter.h" #include "uxio.h"
#define PCI_BADDR0 0x10 #define PCI_BADDR1 0x14 #define PCI_BADDR2 0x18
#define DIVAS_SIGNATURE 0x4447
/* offset to start of MAINT area (used by xlog) */
#define DIVAS_MAINT_OFFSET 0xff00 /* value for BRI card */
#define PROTCAP_TELINDUS 0x1 #define PROTCAP_V90D 0x8
word GetProtFeatureValue(char *sw_id); byte io_in(ADAPTER *a, void *adr); word io_inw(ADAPTER *a, void *adr); void io_in_buffer(ADAPTER *a, void *adr, void *P, word length); void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e); void io_out(ADAPTER *a, void *adr, byte data); void io_outw(ADAPTER *a, void *adr, word data); void io_out_buffer(ADAPTER *a, void *adr, void *P, word length); void io_inc(ADAPTER *a, void *adr);
static int diva_server_bri_test_int(card_t *card); static int bri_ISR (card_t* card);
#define PLX_IOBASE 0 #define DIVAS_IOBASE 1
#define REG_DATA 0x00 #define REG_ADDRLO 0x04 #define REG_ADDRHI 0x0C #define REG_IOCTRL 0x10
#define M_PCI_RESET 0x10
byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset); word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset); void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte); void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
int DivasBRIInitPCI(card_t *card, dia_card_t *cfg);
static int diva_server_bri_reset(card_t *card) { byte *DivasIOBase; word i; dword dwWait;
UxCardLog(0);
DPRINTF(("divas: resetting BRI adapter"));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0);
for (i=0; i < 50000; i++) ;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0); UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x0000);
for (i=0; i<0x8000; i++) { UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0); }
for (dwWait=0; dwWait < 0x00FFFFFF; dwWait++) ;
UxCardMemDetach(card->hw, DivasIOBase);
return 0; }
static void diva_server_bri_reset_int(card_t *card) { byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
UxCardMemDetach(card->hw, DivasIOBase);
return; }
static int diva_server_bri_start(card_t *card, byte *channels) { byte *DivasIOBase, *PLXIOBase; word wSig = 0; word i; dword dwSerialNum; byte bPLX9060 = FALSE;
DPRINTF(("divas: starting Diva Server BRI card"));
card->is_live = FALSE;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0); UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
/* wait for signature to indicate card has started */ for (i = 0; i < 300; i++) { UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E); wSig = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
if (wSig == DIVAS_SIGNATURE) { DPRINTF(("divas: card started after %d ms", i * 10)); break; } UxPause(10); }
if (wSig != DIVAS_SIGNATURE) { DPRINTF(("divas: card failed to start (Sig=0x%x)", wSig)); UxCardMemDetach(card->hw, DivasIOBase); return -1; }
card->is_live = TRUE;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x3F6); *channels = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
UxCardMemDetach(card->hw, DivasIOBase);
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) | UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
if (bPLX9060) { dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x1E) << 16) | (UxCardPortIoInW(card->hw, PLXIOBase, 0x22)); DPRINTF(("divas: PLX9060 in use. Serial number 0x%04X", dwSerialNum)); } else { dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x22) << 16) | (UxCardPortIoInW(card->hw, PLXIOBase, 0x26)); DPRINTF(("divas: PLX9050 in use. Serial number 0x%04X", dwSerialNum)); }
UxCardMemDetach(card->hw, PLXIOBase);
card->serial_no = dwSerialNum;
diva_server_bri_test_int(card); return 0; }
static int diva_server_bri_load(card_t *card, dia_load_t *load) { byte *DivasIOBase; dword r3000_base; dword dwAddr, dwLength, i; word wTest, aWord;
DPRINTF(("divas: loading Diva Server BRI card"));
switch (load->code_type) { case DIA_CPU_CODE: DPRINTF(("divas: loading RISC %s", &load->code[0x80]));
card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]); DPRINTF(("divas: features 0x%x", card->hw->features)); if (card->hw->features == 0xFFFF) { DPRINTF(("divas: invalid feature string failed load\n")); return -1; }
r3000_base = 0; break;
case DIA_DSP_CODE: DPRINTF(("divas: DSP code \"%s\"", load->code));
if ((card->hw->features) && (!(card->hw->features & PROTCAP_TELINDUS))) { DPRINTF(("divas: only Telindus style binaries supported")); return -1; }
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D)) { DPRINTF(("divas: V.90 DSP binary")); r3000_base = (0xBF790000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC)); } else { DPRINTF(("divas: non-V.90 DSP binary")); r3000_base = (0xBF7A0000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC)); } DPRINTF(("divas: loading at 0x%x", r3000_base)); break;
case DIA_TABLE_CODE: DPRINTF(("divas: TABLE code")); if ((card->hw->features) && (card->hw->features & PROTCAP_V90D)) { r3000_base = 0xBF790000 + sizeof(dword); } else { r3000_base = 0xBF7A0000 + sizeof(dword); }
break;
case DIA_DLOAD_CNT: DPRINTF(("divas: COUNT code")); if ((card->hw->features) && (card->hw->features & PROTCAP_V90D)) { r3000_base = 0xBF790000; } else { r3000_base = 0xBF7A0000; } break;
default: DPRINTF(("divas: unknown code type %d", load->code_type)); return -1; break; }
DPRINTF(("divas: Writing %d bytes to adapter, address 0x%x", load->length, r3000_base));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
DPRINTF(("divas: Attached to 0x%04X", DivasIOBase));
dwLength = load->length;
for (i=0; i < dwLength; i++) { dwAddr = r3000_base + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, load->code[i]); }
DPRINTF(("divas: Verifying"));
for (i=0; i<dwLength; i++) { dwAddr = r3000_base + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
wTest = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
aWord = load->code[i];
if (wTest != aWord) { DPRINTF(("divas: load verify failed on byte %d", i)); DPRINTF(("divas: RAM 0x%x File 0x%x",wTest,aWord)); UxCardMemDetach(card->hw, DivasIOBase);
return -1; } }
DPRINTF(("divas: Loaded and verified. Detaching from adapter"));
UxCardMemDetach(card->hw, DivasIOBase);
UxCardLog(0);
return 0; }
static int diva_server_bri_config(card_t *card, dia_config_t *config) { byte *DivasIOBase, i;
DPRINTF(("divas: configuring Diva Server BRI card"));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 8); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->tei);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 9); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->nt2);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 10); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->sig_flags);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 11); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->watchdog);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 12); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->permanent);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 13); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 14); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->stable_l2);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 15); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->no_order_check);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 16); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 17); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 18); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->low_channel);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 19); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->prot_version);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 20); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->crc4);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 21); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D)) { DPRINTF(("divas: Signifying V.90")); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 4); } else { UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0); }
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 23); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, card->serial_no & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 24); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 8) & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 25); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 16) & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 26); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 21);
for (i=0; i<32; i++) { UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 32+i); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].oad[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 64+i); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].osa[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 96+i); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].spid[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 128+i); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].oad[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 160+i); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].osa[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 192+i); UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].spid[i]); }
UxCardMemDetach(card->hw, DivasIOBase);
return 0; }
void DivasBriPatch(card_t *card) { dword PLXIOBase = 0; dword DivasIOBase = 0;
PLXIOBase = card->cfg.reset_base; DivasIOBase = card->cfg.io_base;
if(card->hw == NULL) { DPRINTF(("Divas: BRI PATCH (PLX chip) card->hw is null")); return; }
if (PLXIOBase == 0) { DPRINTF(("Divas: BRI (PLX chip) cannot be patched. The BRI adapter may")); DPRINTF(("Divas: not function properly. If you do encounter problems,")); DPRINTF(("Divas: ensure that your machine is using the latest BIOS.")); return; }
DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase)); DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
if (PLXIOBase & 0x80) { dword dwSize, dwSerialNum, dwCmd; boolean_t bPLX9060; word wSerHi, wSerLo;
DPRINTF(("Divas: Patch required")); dwCmd = 0; UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
PLXIOBase &= ~0x80; UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &PLXIOBase);
dwSize = 0xFFFFFFFF; UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &dwSize); UxPciConfigRead(card->hw, 4, PCI_BADDR1, &dwSize); dwSize = (~ (dwSize & ~7)) + 1;
DivasIOBase = PLXIOBase + dwSize;
card->cfg.reset_base = PLXIOBase; card->cfg.io_base = DivasIOBase; UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &card->cfg.reset_base); UxPciConfigWrite(card->hw, 4, PCI_BADDR2, &card->cfg.io_base);
dwCmd = 5; UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) | UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
if (bPLX9060) { wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E); wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22); dwSerialNum = (wSerHi << 16) | wSerLo; UxCardLog(0); } else { wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22); wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26); dwSerialNum = (wSerHi << 16) | wSerLo; UxCardLog(0); } } else { word wSerHi, wSerLo; boolean_t bPLX9060; dword dwSerialNum;
DPRINTF(("divas: No patch required"));
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) | UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
if (bPLX9060) { wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E); wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22); dwSerialNum = (wSerHi << 16) | wSerLo; } else { wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22); wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26); dwSerialNum = (wSerHi << 16) | wSerLo; } } DPRINTF(("Divas: After patching:")); DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase)); DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
}
#define TEST_INT_DIVAS_BRI 0x12 static int diva_server_bri_test_int(card_t *card) { boolean_t bPLX9060 = FALSE; byte *PLXIOBase = NULL, *DivasIOBase = NULL;
DPRINTF(("divas: test interrupt for Diva Server BRI card"));
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) || UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
if (bPLX9060) { /* PLX9060 */ UxCardPortIoOut(card->hw, PLXIOBase, 0x69, 0x09); } else { /* PLX9050 */ UxCardPortIoOut(card->hw, PLXIOBase, 0x4C, 0x41); }
card->test_int_pend = TEST_INT_DIVAS_BRI;
UxCardMemDetach(card->hw, PLXIOBase);
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x89);
UxCardMemDetach(card->hw, DivasIOBase); return 0; }
static int diva_server_bri_mem_get(card_t *card, mem_block_t *mem_block) { dword user_addr = mem_block->addr; word length = 0; dword addr; word i; byte *DivasIOBase;
DPRINTF(("divas: Retrieving memory from 0x%x", user_addr));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
addr = user_addr;
for (i=0; i < (16 * 8); i++) { addr = user_addr + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, addr >> 16); UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, (word) addr);
mem_block->data[i] = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA); length++; }
UxCardMemDetach(card->hw, DivasIOBase);
return length; }
int DivasBriInit(card_t *card, dia_card_t *cfg) { DPRINTF(("divas: initialise Diva Server BRI card"));
if (DivasBRIInitPCI(card, cfg) == -1) { return -1; }
card->card_reset = diva_server_bri_reset; card->card_start = diva_server_bri_start; card->card_load = diva_server_bri_load; card->card_config = diva_server_bri_config; card->reset_int = diva_server_bri_reset_int; card->card_mem_get = diva_server_bri_mem_get;
card->xlog_offset = DIVAS_MAINT_OFFSET;
card->out = DivasOut; card->test_int = DivasTestInt; card->dpc = DivasDpc; card->clear_int = DivasClearInt; card->card_isr = bri_ISR;
card->a.ram_out = io_out; card->a.ram_outw = io_outw; card->a.ram_out_buffer = io_out_buffer; card->a.ram_inc = io_inc;
card->a.ram_in = io_in; card->a.ram_inw = io_inw; card->a.ram_in_buffer = io_in_buffer; card->a.ram_look_ahead = io_look_ahead;
return 0; }
word GetProtFeatureValue(char *sw_id) { word features = 0;
while ((*sw_id) && (sw_id[0] != '[')) sw_id++;
if (sw_id == NULL) { DPRINTF(("divas: no feature string present")); features = -1; } else { byte i, shifter;
sw_id += 3;
for (i=0, shifter=12; i<4; i++, shifter-=4) { if ((sw_id[i] >= '0') && (sw_id[i] <= '9')) { features |= (sw_id[i] - '0') << shifter; } else if ((sw_id[i] >= 'a') && (sw_id[i] <= 'f')) { features |= (sw_id[i] - 'a' + 10) << shifter; } else if ((sw_id[i] >= 'A') && (sw_id[i] <= 'F')) { features |= (sw_id[i] - 'A' + 10) << shifter; } else { DPRINTF(("divas: invalid feature string")); return -1; } } }
return features; }
int bri_ISR (card_t* card) { int served = 0; byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01) { served = 1; card->int_pend += 1; DivasDpcSchedule(); /* ISR DPC */ UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08); }
UxCardMemDetach(card->hw, DivasIOBase);
return (served != 0); }
|