1/* 2 * Diva Server PRI specific part of initialisation 3 * 4 * Copyright (C) Eicon Technology Corporation, 2000. 5 * 6 * Eicon File Revision : 1.5 7 * 8 * This software may be used and distributed according to the terms 9 * of the GNU General Public License, incorporated herein by reference. 10 * 11 */ 12 13#include "sys.h" 14#include "idi.h" 15#include "divas.h" 16#include "pc.h" 17#include "pr_pc.h" 18#include "dsp_defs.h" 19 20#include "adapter.h" 21#include "uxio.h" 22 23#define DIVAS_LOAD_CMD 0x02 24#define DIVAS_START_CMD 0x03 25#define DIVAS_IRQ_RESET 0xC18 26#define DIVAS_IRQ_RESET_VAL 0xFE 27 28#define TEST_INT_DIVAS 0x11 29#define TEST_INT_DIVAS_BRI 0x12 30 31#define DIVAS_RESET 0x81 32#define DIVAS_LED1 0x04 33#define DIVAS_LED2 0x08 34#define DIVAS_LED3 0x20 35#define DIVAS_LED4 0x40 36 37#define DIVAS_RESET_REG 0x20 38 39#define DIVAS_SIGNATURE 0x4447 40 41/* offset to start of MAINT area (used by xlog) */ 42 43#define DIVAS_MAINT_OFFSET 0xef00 /* value for PRI card */ 44 45#define MP_PROTOCOL_ADDR 0xA0011000 46#define MP_DSP_CODE_BASE 0xa03a0000 47 48typedef struct { 49 dword cmd; 50 dword addr; 51 dword len; 52 dword err; 53 dword live; 54 dword reserved[(0x1020>>2)-6]; 55 dword signature; 56 byte data[1]; 57} diva_server_boot_t; 58 59byte mem_in(ADAPTER *a, void *adr); 60word mem_inw(ADAPTER *a, void *adr); 61void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length); 62void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e); 63void mem_out(ADAPTER *a, void *adr, byte data); 64void mem_outw(ADAPTER *a, void *adr, word data); 65void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length); 66void mem_inc(ADAPTER *a, void *adr); 67 68int DivasPRIInitPCI(card_t *card, dia_card_t *cfg); 69static int pri_ISR (card_t* card); 70 71static int diva_server_reset(card_t *card) 72{ 73 byte *reg; 74 diva_server_boot_t *boot = NULL; 75 dword live = 0; 76 int i = 0; 77 dword dwWait; 78 79 DPRINTF(("divas: reset Diva Server PRI")); 80 81 reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY); 82 83 UxCardMemOut(card->hw, ®[DIVAS_RESET_REG], DIVAS_RESET | 84 DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4); 85 86 for (dwWait = 0x000fffff; dwWait; dwWait--) 87 ; 88 89 UxCardMemOut(card->hw, ®[DIVAS_RESET_REG], 0x00); 90 91 for (dwWait = 0x000fffff; dwWait; dwWait--) 92 ; 93 94 UxCardMemDetach(card->hw, reg); 95 96 boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY); 97 98 UxCardMemOutD(card->hw, boot->reserved, 0); 99 100 live = UxCardMemInD(card->hw, &boot->live); 101 102 for (i=0; i<5; i++) 103 { 104 if (live != UxCardMemInD(card->hw, &boot->live)) 105 { 106 break; 107 } 108 UxPause(10); 109 } 110 111 if (i == 5) 112 { 113 UxCardMemDetach(card->hw, boot); 114 115 DPRINTF(("divas: card is reset but CPU not running")); 116 return -1; 117 } 118 119 UxCardMemDetach(card->hw, boot); 120 121 DPRINTF(("divas: card reset after %d ms", i * 10)); 122 123 return 0; 124} 125 126static int diva_server_config(card_t *card, dia_config_t *config) 127{ 128 byte *shared; 129 int i, j; 130 131 DPRINTF(("divas: configure Diva Server PRI")); 132 133 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 134 135 UxCardLog(0); 136 for (i=0; i<256; i++) 137 { 138 UxCardMemOut(card->hw, &shared[i], 0); 139 } 140 141 UxCardMemOut(card->hw, &shared[ 8], config->tei); 142 UxCardMemOut(card->hw, &shared[ 9], config->nt2); 143 UxCardMemOut(card->hw, &shared[10], config->sig_flags); 144 UxCardMemOut(card->hw, &shared[11], config->watchdog); 145 UxCardMemOut(card->hw, &shared[12], config->permanent); 146 UxCardMemOut(card->hw, &shared[13], config->x_interface); 147 UxCardMemOut(card->hw, &shared[14], config->stable_l2); 148 UxCardMemOut(card->hw, &shared[15], config->no_order_check); 149 UxCardMemOut(card->hw, &shared[16], config->handset_type); 150 UxCardMemOut(card->hw, &shared[17], 0); 151 UxCardMemOut(card->hw, &shared[18], config->low_channel); 152 UxCardMemOut(card->hw, &shared[19], config->prot_version); 153 UxCardMemOut(card->hw, &shared[20], config->crc4); 154 155 for (i=0; i<2; i++) 156 { 157 for (j=0; j<32; j++) 158 { 159 UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]); 160 } 161 162 for (j=0; j<32; j++) 163 { 164 UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]); 165 } 166 167 for (j=0; j<32; j++) 168 { 169 UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]); 170 } 171 } 172 173 UxCardMemDetach(card->hw, shared); 174 175 return 0; 176} 177 178static 179void diva_server_reset_int(card_t *card) 180{ 181 byte *cfg; 182 183 cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY); 184 185 UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET], DIVAS_IRQ_RESET_VAL); 186 UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET + 2], 0); 187 UxCardMemDetach(card->hw, cfg); 188 189 return; 190} 191 192 193static int diva_server_test_int(card_t *card) 194{ 195 int i; 196 byte *shared; 197 byte req_int; 198 199 DPRINTF(("divas: test interrupt for Diva Server PRI")); 200 201 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 202 203 UxCardMemIn(card->hw, &shared[0x3FE]); 204 UxCardMemOut(card->hw, &shared[0x3FE], 0); 205 UxCardMemIn(card->hw, &shared[0x3FE]); 206 207 UxCardMemDetach(card->hw, shared); 208 209 diva_server_reset_int(card); 210 211 shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY); 212 213 card->test_int_pend = TEST_INT_DIVAS; 214 215 req_int = UxCardMemIn(card->hw, &(((struct pr_ram *)shared)->ReadyInt)); 216 217 req_int++; 218 219 UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->ReadyInt), req_int); 220 221 UxCardMemDetach(card->hw, shared); 222 223 UxCardLog(0); 224 for (i = 0; i < 50; i++) 225 { 226 if (!card->test_int_pend) 227 { 228 break; 229 } 230 UxPause(10); 231 } 232 233 234 if (card->test_int_pend) 235 { 236 237 DPRINTF(("active: timeout waiting for card to interrupt")); 238 return (-1); 239 240 } 241 242 return 0; 243} 244 245 246static void print_hdr(unsigned char *code, int offset) 247{ 248 unsigned char hdr[80]; 249 int i; 250 251 i = 0; 252 253 while ((i < (DIM(hdr) -1)) && 254 (code[offset + i] != '\0') && 255 (code[offset + i] != '\r') && 256 (code[offset + i] != '\n')) 257 { 258 hdr[i] = code[offset + i]; 259 i++; 260 } 261 262 hdr[i] = '\0'; 263 264 DPRINTF(("divas: loading %s", hdr)); 265} 266 267static int diva_server_load(card_t *card, dia_load_t *load) 268{ 269 diva_server_boot_t *boot; 270 int i, offset, length; 271 dword cmd = 0; 272 273 DPRINTF(("divas: loading Diva Server PRI")); 274 275 boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY); 276 277 switch(load->code_type) 278 { 279 case DIA_CPU_CODE: 280 DPRINTF(("divas: RISC code")); 281 print_hdr(load->code, 0x80); 282 283 UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR); 284 break; 285 286 case DIA_DSP_CODE: 287 DPRINTF(("divas: DSP code")); 288 print_hdr(load->code, 0x0); 289 290 UxCardMemOutD(card->hw, &boot->addr, 291 (MP_DSP_CODE_BASE + (((sizeof(dword) + 292 (sizeof(t_dsp_download_desc) * DSP_MAX_DOWNLOAD_COUNT)) 293 + ~ALIGNMENT_MASK_MAESTRA) & ALIGNMENT_MASK_MAESTRA))); 294 break; 295 296 case DIA_TABLE_CODE: 297 DPRINTF(("divas: TABLE code")); 298 UxCardMemOutD(card->hw, &boot->addr, 299 (MP_DSP_CODE_BASE + sizeof(dword))); 300 break; 301 302 case DIA_CONT_CODE: 303 DPRINTF(("divas: continuation code")); 304 break; 305 306 case DIA_DLOAD_CNT: 307 DPRINTF(("divas: COUNT code")); 308 UxCardMemOutD(card->hw, &boot->addr, MP_DSP_CODE_BASE); 309 break; 310 311 default: 312 DPRINTF(("divas: unknown code type")); 313 UxCardMemDetach(card->hw, boot); 314 return -1; 315 } 316 317 UxCardLog(0); 318 offset = 0; 319 320 do 321 { 322 length = (load->length - offset >= 400) ? 400 : load->length - offset; 323 324 for (i=0; i<length; i++) 325 { 326 UxCardMemOut(card->hw, &boot->data[i], load->code[offset+i]); 327 } 328 329 for (i=0; i<length; i++) 330 { 331 if (load->code[offset + i] != UxCardMemIn(card->hw, &boot->data[i])) 332 { 333 UxCardMemDetach(card->hw, boot); 334 335 DPRINTF(("divas: card code block verify failed")); 336 return -1; 337 } 338 } 339 340 UxCardMemOutD(card->hw, &boot->len, (length + 3) / 4); 341 UxCardMemOutD(card->hw, &boot->cmd, DIVAS_LOAD_CMD); 342 343 for (i=0; i<50000; i++) 344 { 345 cmd = UxCardMemInD(card->hw, &boot->cmd); 346 if (!cmd) 347 { 348 break; 349 } 350 /*UxPause(1);*/ 351 } 352 353 if (cmd) 354 { 355 DPRINTF(("divas: timeout waiting for card to ACK load (offset = %d)", offset)); 356 UxCardMemDetach(card->hw, boot); 357 return -1; 358 } 359 360 offset += length; 361 362 } while (offset < load->length); 363 364 UxCardMemDetach(card->hw, boot); 365 366 DPRINTF(("divas: DIVA Server card loaded")); 367 368 return 0; 369} 370 371static int diva_server_start(card_t *card, byte *channels) 372{ 373 diva_server_boot_t *boot; 374 byte *ram; 375 int i; 376 dword signature = 0; 377 378 DPRINTF(("divas: start Diva Server PRI")); 379 380 card->is_live = FALSE; 381 382 boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY); 383 384 UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR); 385 UxCardMemOutD(card->hw, &boot->cmd, DIVAS_START_CMD); 386 387 UxCardLog(0); 388 389 for (i = 0; i < 300; i++) 390 { 391 signature = UxCardMemInD(card->hw, &boot->signature); 392 if ((signature >> 16) == DIVAS_SIGNATURE) 393 { 394 DPRINTF(("divas: started card after %d ms", i * 10)); 395 break; 396 } 397 UxPause(10); 398 } 399 400 if ((signature >> 16) != DIVAS_SIGNATURE) 401 { 402 UxCardMemDetach(card->hw, boot); 403 DPRINTF(("divas: timeout waiting for card to run protocol code (sig = 0x%x)", signature)); 404 return -1; 405 } 406 407 card->is_live = TRUE; 408 409 ram = (byte *) boot; 410 ram += DIVAS_SHARED_OFFSET; 411 412 *channels = UxCardMemIn(card->hw, &ram[0x3F6]); 413 card->serial_no = UxCardMemInD(card->hw, &ram[0x3F0]); 414 415 UxCardMemDetach(card->hw, boot); 416 417 if (diva_server_test_int(card)) 418 { 419 DPRINTF(("divas: interrupt test failed")); 420 return -1; 421 } 422 423 DPRINTF(("divas: DIVA Server card started")); 424 425 return 0; 426} 427 428static 429int diva_server_mem_get(card_t *card, mem_block_t *mem_block) 430 431{ 432 byte *a; 433 byte *card_addr; 434 word length = 0; 435 int i; 436 437 a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY); 438 439 card_addr = a; 440 card_addr += mem_block->addr; 441 442 for (i=0; i < sizeof(mem_block->data); i++) 443 { 444 mem_block->data[i] = UxCardMemIn(card->hw, card_addr); 445 card_addr++; 446 length++; 447 } 448 449 UxCardMemDetach(card->hw, a); 450 451 return length; 452} 453 454/* 455 * Initialise PRI specific entry points 456 */ 457 458int DivasPriInit(card_t *card, dia_card_t *cfg) 459{ 460 DPRINTF(("divas: initialise Diva Server PRI")); 461 462 if (DivasPRIInitPCI(card, cfg) == -1) 463 { 464 return -1; 465 } 466 467 card->card_reset = diva_server_reset; 468 card->card_load = diva_server_load; 469 card->card_config = diva_server_config; 470 card->card_start = diva_server_start; 471 card->reset_int = diva_server_reset_int; 472 card->card_mem_get = diva_server_mem_get; 473 474 card->xlog_offset = DIVAS_MAINT_OFFSET; 475 476 card->out = DivasOut; 477 card->test_int = DivasTestInt; 478 card->dpc = DivasDpc; 479 card->clear_int = DivasClearInt; 480 card->card_isr = pri_ISR; 481 482 card->a.ram_out = mem_out; 483 card->a.ram_outw = mem_outw; 484 card->a.ram_out_buffer = mem_out_buffer; 485 card->a.ram_inc = mem_inc; 486 487 card->a.ram_in = mem_in; 488 card->a.ram_inw = mem_inw; 489 card->a.ram_in_buffer = mem_in_buffer; 490 card->a.ram_look_ahead = mem_look_ahead; 491 492 return 0; 493} 494 495 496static int pri_ISR (card_t* card) 497{ 498 int served = 0; 499 byte* cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY); 500 volatile unsigned long* isr = (unsigned long*)&cfg[DIVAS_IRQ_RESET]; 501 register unsigned long val = *isr; 502 503 if (val & 0x80000000) /* our card had caused interrupt ??? */ 504 { 505 served = 1; 506 card->int_pend += 1; 507 DivasDpcSchedule(); /* ISR DPC */ 508 509 *isr = (unsigned long)~0x03E00000; /* Clear interrupt line */ 510 } 511 512 UxCardMemDetach(card->hw, cfg); 513 514 return (served != 0); 515} 516 517 518