s_4bri.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. *
  3. Copyright (c) Eicon Networks, 2002.
  4. *
  5. This source file is supplied for the use with
  6. Eicon Networks range of DIVA Server Adapters.
  7. *
  8. Eicon File Revision : 2.1
  9. *
  10. This program is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 2, or (at your option)
  13. any later version.
  14. *
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
  17. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18. See the GNU General Public License for more details.
  19. *
  20. You should have received a copy of the GNU General Public License
  21. along with this program; if not, write to the Free Software
  22. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. *
  24. */
  25. #include "platform.h"
  26. #include "di_defs.h"
  27. #include "pc.h"
  28. #include "pr_pc.h"
  29. #include "di.h"
  30. #include "mi_pc.h"
  31. #include "pc_maint.h"
  32. #include "divasync.h"
  33. #include "pc_init.h"
  34. #include "io.h"
  35. #include "helpers.h"
  36. #include "dsrv4bri.h"
  37. #include "dsp_defs.h"
  38. #include "sdp_hdr.h"
  39. /*****************************************************************************/
  40. #define MAX_XLOG_SIZE (64 * 1024)
  41. /* --------------------------------------------------------------------------
  42. Recovery XLOG from QBRI Card
  43. -------------------------------------------------------------------------- */
  44. static void qBri_cpu_trapped(PISDN_ADAPTER IoAdapter) {
  45. byte __iomem *base;
  46. word *Xlog;
  47. dword regs[4], TrapID, offset, size;
  48. Xdesc xlogDesc;
  49. int factor = (IoAdapter->tasks == 1) ? 1 : 2;
  50. /*
  51. * check for trapped MIPS 46xx CPU, dump exception frame
  52. */
  53. base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter);
  54. offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor);
  55. TrapID = READ_DWORD(&base[0x80]);
  56. if ((TrapID == 0x99999999) || (TrapID == 0x99999901))
  57. {
  58. dump_trap_frame(IoAdapter, &base[0x90]);
  59. IoAdapter->trapped = 1;
  60. }
  61. regs[0] = READ_DWORD((base + offset) + 0x70);
  62. regs[1] = READ_DWORD((base + offset) + 0x74);
  63. regs[2] = READ_DWORD((base + offset) + 0x78);
  64. regs[3] = READ_DWORD((base + offset) + 0x7c);
  65. regs[0] &= IoAdapter->MemorySize - 1;
  66. if ((regs[0] >= offset)
  67. && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1))
  68. {
  69. if (!(Xlog = (word *)diva_os_malloc(0, MAX_XLOG_SIZE))) {
  70. DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
  71. return;
  72. }
  73. size = offset + (IoAdapter->MemorySize >> factor) - regs[0];
  74. if (size > MAX_XLOG_SIZE)
  75. size = MAX_XLOG_SIZE;
  76. memcpy_fromio(Xlog, &base[regs[0]], size);
  77. xlogDesc.buf = Xlog;
  78. xlogDesc.cnt = READ_WORD(&base[regs[1] & (IoAdapter->MemorySize - 1)]);
  79. xlogDesc.out = READ_WORD(&base[regs[2] & (IoAdapter->MemorySize - 1)]);
  80. dump_xlog_buffer(IoAdapter, &xlogDesc);
  81. diva_os_free(0, Xlog);
  82. IoAdapter->trapped = 2;
  83. }
  84. DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base);
  85. }
  86. /* --------------------------------------------------------------------------
  87. Reset QBRI Hardware
  88. -------------------------------------------------------------------------- */
  89. static void reset_qBri_hardware(PISDN_ADAPTER IoAdapter) {
  90. word volatile __iomem *qBriReset;
  91. byte volatile __iomem *qBriCntrl;
  92. byte volatile __iomem *p;
  93. qBriReset = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
  94. WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET);
  95. diva_os_wait(1);
  96. WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET);
  97. diva_os_wait(1);
  98. WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_RELOAD_EEPROM);
  99. diva_os_wait(1);
  100. WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM);
  101. diva_os_wait(1);
  102. DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset);
  103. qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
  104. p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
  105. WRITE_DWORD(p, 0);
  106. DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl);
  107. DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset))
  108. DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p))
  109. }
  110. /* --------------------------------------------------------------------------
  111. Start Card CPU
  112. -------------------------------------------------------------------------- */
  113. void start_qBri_hardware(PISDN_ADAPTER IoAdapter) {
  114. byte volatile __iomem *qBriReset;
  115. byte volatile __iomem *p;
  116. p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
  117. qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)];
  118. WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK);
  119. diva_os_wait(2);
  120. WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
  121. diva_os_wait(10);
  122. DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
  123. DBG_TRC(("started processor @ addr 0x%08lx", qBriReset))
  124. }
  125. /* --------------------------------------------------------------------------
  126. Stop Card CPU
  127. -------------------------------------------------------------------------- */
  128. static void stop_qBri_hardware(PISDN_ADAPTER IoAdapter) {
  129. byte volatile __iomem *p;
  130. dword volatile __iomem *qBriReset;
  131. dword volatile __iomem *qBriIrq;
  132. dword volatile __iomem *qBriIsacDspReset;
  133. int rev2 = DIVA_4BRI_REVISION(IoAdapter);
  134. int reset_offset = rev2 ? (MQ2_BREG_RISC) : (MQ_BREG_RISC);
  135. int irq_offset = rev2 ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST);
  136. int hw_offset = rev2 ? (MQ2_ISAC_DSP_RESET) : (MQ_ISAC_DSP_RESET);
  137. if (IoAdapter->ControllerNumber > 0)
  138. return;
  139. p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
  140. qBriReset = (dword volatile __iomem *)&p[reset_offset];
  141. qBriIsacDspReset = (dword volatile __iomem *)&p[hw_offset];
  142. /*
  143. * clear interrupt line (reset Local Interrupt Test Register)
  144. */
  145. WRITE_DWORD(qBriReset, 0);
  146. WRITE_DWORD(qBriIsacDspReset, 0);
  147. DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
  148. p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
  149. WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */
  150. DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
  151. p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
  152. qBriIrq = (dword volatile __iomem *)&p[irq_offset];
  153. WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
  154. DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
  155. DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset))
  156. }
  157. /* --------------------------------------------------------------------------
  158. FPGA download
  159. -------------------------------------------------------------------------- */
  160. #define FPGA_NAME_OFFSET 0x10
  161. static byte *qBri_check_FPGAsrc(PISDN_ADAPTER IoAdapter, char *FileName,
  162. dword *Length, dword *code) {
  163. byte *File;
  164. char *fpgaFile, *fpgaType, *fpgaDate, *fpgaTime;
  165. dword fpgaFlen, fpgaTlen, fpgaDlen, cnt, year, i;
  166. if (!(File = (byte *)xdiLoadFile(FileName, Length, 0))) {
  167. return (NULL);
  168. }
  169. /*
  170. * scan file until FF and put id string into buffer
  171. */
  172. for (i = 0; File[i] != 0xff;)
  173. {
  174. if (++i >= *Length)
  175. {
  176. DBG_FTL(("FPGA download: start of data header not found"))
  177. xdiFreeFile(File);
  178. return (NULL);
  179. }
  180. }
  181. *code = i++;
  182. if ((File[i] & 0xF0) != 0x20)
  183. {
  184. DBG_FTL(("FPGA download: data header corrupted"))
  185. xdiFreeFile(File);
  186. return (NULL);
  187. }
  188. fpgaFlen = (dword)File[FPGA_NAME_OFFSET - 1];
  189. if (fpgaFlen == 0)
  190. fpgaFlen = 12;
  191. fpgaFile = (char *)&File[FPGA_NAME_OFFSET];
  192. fpgaTlen = (dword)fpgaFile[fpgaFlen + 2];
  193. if (fpgaTlen == 0)
  194. fpgaTlen = 10;
  195. fpgaType = (char *)&fpgaFile[fpgaFlen + 3];
  196. fpgaDlen = (dword) fpgaType[fpgaTlen + 2];
  197. if (fpgaDlen == 0)
  198. fpgaDlen = 11;
  199. fpgaDate = (char *)&fpgaType[fpgaTlen + 3];
  200. fpgaTime = (char *)&fpgaDate[fpgaDlen + 3];
  201. cnt = (dword)(((File[i] & 0x0F) << 20) + (File[i + 1] << 12)
  202. + (File[i + 2] << 4) + (File[i + 3] >> 4));
  203. if ((dword)(i + (cnt / 8)) > *Length)
  204. {
  205. DBG_FTL(("FPGA download: '%s' file too small (%ld < %ld)",
  206. FileName, *Length, code + ((cnt + 7) / 8)))
  207. xdiFreeFile(File);
  208. return (NULL);
  209. }
  210. i = 0;
  211. do
  212. {
  213. while ((fpgaDate[i] != '\0')
  214. && ((fpgaDate[i] < '0') || (fpgaDate[i] > '9')))
  215. {
  216. i++;
  217. }
  218. year = 0;
  219. while ((fpgaDate[i] >= '0') && (fpgaDate[i] <= '9'))
  220. year = year * 10 + (fpgaDate[i++] - '0');
  221. } while ((year < 2000) && (fpgaDate[i] != '\0'));
  222. switch (IoAdapter->cardType) {
  223. case CARDTYPE_DIVASRV_B_2F_PCI:
  224. break;
  225. default:
  226. if (year >= 2001) {
  227. IoAdapter->fpga_features |= PCINIT_FPGA_PLX_ACCESS_SUPPORTED;
  228. }
  229. }
  230. DBG_LOG(("FPGA[%s] file %s (%s %s) len %d",
  231. fpgaType, fpgaFile, fpgaDate, fpgaTime, cnt))
  232. return (File);
  233. }
  234. /******************************************************************************/
  235. #define FPGA_PROG 0x0001 /* PROG enable low */
  236. #define FPGA_BUSY 0x0002 /* BUSY high, DONE low */
  237. #define FPGA_CS 0x000C /* Enable I/O pins */
  238. #define FPGA_CCLK 0x0100
  239. #define FPGA_DOUT 0x0400
  240. #define FPGA_DIN FPGA_DOUT /* bidirectional I/O */
  241. int qBri_FPGA_download(PISDN_ADAPTER IoAdapter) {
  242. int bit;
  243. byte *File;
  244. dword code, FileLength;
  245. word volatile __iomem *addr = (word volatile __iomem *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter);
  246. word val, baseval = FPGA_CS | FPGA_PROG;
  247. if (DIVA_4BRI_REVISION(IoAdapter))
  248. {
  249. char *name;
  250. switch (IoAdapter->cardType) {
  251. case CARDTYPE_DIVASRV_B_2F_PCI:
  252. name = "dsbri2f.bit";
  253. break;
  254. case CARDTYPE_DIVASRV_B_2M_V2_PCI:
  255. case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
  256. name = "dsbri2m.bit";
  257. break;
  258. default:
  259. name = "ds4bri2.bit";
  260. }
  261. File = qBri_check_FPGAsrc(IoAdapter, name,
  262. &FileLength, &code);
  263. }
  264. else
  265. {
  266. File = qBri_check_FPGAsrc(IoAdapter, "ds4bri.bit",
  267. &FileLength, &code);
  268. }
  269. if (!File) {
  270. DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
  271. return (0);
  272. }
  273. /*
  274. * prepare download, pulse PROGRAM pin down.
  275. */
  276. WRITE_WORD(addr, baseval & ~FPGA_PROG); /* PROGRAM low pulse */
  277. WRITE_WORD(addr, baseval); /* release */
  278. diva_os_wait(50); /* wait until FPGA finished internal memory clear */
  279. /*
  280. * check done pin, must be low
  281. */
  282. if (READ_WORD(addr) & FPGA_BUSY)
  283. {
  284. DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing"))
  285. xdiFreeFile(File);
  286. DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
  287. return (0);
  288. }
  289. /*
  290. * put data onto the FPGA
  291. */
  292. while (code < FileLength)
  293. {
  294. val = ((word)File[code++]) << 3;
  295. for (bit = 8; bit-- > 0; val <<= 1) /* put byte onto FPGA */
  296. {
  297. baseval &= ~FPGA_DOUT; /* clr data bit */
  298. baseval |= (val & FPGA_DOUT); /* copy data bit */
  299. WRITE_WORD(addr, baseval);
  300. WRITE_WORD(addr, baseval | FPGA_CCLK); /* set CCLK hi */
  301. WRITE_WORD(addr, baseval | FPGA_CCLK); /* set CCLK hi */
  302. WRITE_WORD(addr, baseval); /* set CCLK lo */
  303. }
  304. }
  305. xdiFreeFile(File);
  306. diva_os_wait(100);
  307. val = READ_WORD(addr);
  308. DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr);
  309. if (!(val & FPGA_BUSY))
  310. {
  311. DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val))
  312. return (0);
  313. }
  314. return (1);
  315. }
  316. static int load_qBri_hardware(PISDN_ADAPTER IoAdapter) {
  317. return (0);
  318. }
  319. /* --------------------------------------------------------------------------
  320. Card ISR
  321. -------------------------------------------------------------------------- */
  322. static int qBri_ISR(struct _ISDN_ADAPTER *IoAdapter) {
  323. dword volatile __iomem *qBriIrq;
  324. PADAPTER_LIST_ENTRY QuadroList = IoAdapter->QuadroList;
  325. word i;
  326. int serviced = 0;
  327. byte __iomem *p;
  328. p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
  329. if (!(READ_BYTE(&p[PLX9054_INTCSR]) & 0x80)) {
  330. DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
  331. return (0);
  332. }
  333. DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
  334. /*
  335. * clear interrupt line (reset Local Interrupt Test Register)
  336. */
  337. p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
  338. qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]);
  339. WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
  340. DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
  341. for (i = 0; i < IoAdapter->tasks; ++i)
  342. {
  343. IoAdapter = QuadroList->QuadroAdapter[i];
  344. if (IoAdapter && IoAdapter->Initialized
  345. && IoAdapter->tst_irq(&IoAdapter->a))
  346. {
  347. IoAdapter->IrqCount++;
  348. serviced = 1;
  349. diva_os_schedule_soft_isr(&IoAdapter->isr_soft_isr);
  350. }
  351. }
  352. return (serviced);
  353. }
  354. /* --------------------------------------------------------------------------
  355. Does disable the interrupt on the card
  356. -------------------------------------------------------------------------- */
  357. static void disable_qBri_interrupt(PISDN_ADAPTER IoAdapter) {
  358. dword volatile __iomem *qBriIrq;
  359. byte __iomem *p;
  360. if (IoAdapter->ControllerNumber > 0)
  361. return;
  362. /*
  363. * clear interrupt line (reset Local Interrupt Test Register)
  364. */
  365. p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
  366. WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */
  367. DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
  368. p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
  369. qBriIrq = (dword volatile __iomem *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]);
  370. WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
  371. DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
  372. }
  373. /* --------------------------------------------------------------------------
  374. Install Adapter Entry Points
  375. -------------------------------------------------------------------------- */
  376. static void set_common_qBri_functions(PISDN_ADAPTER IoAdapter) {
  377. ADAPTER *a;
  378. a = &IoAdapter->a;
  379. a->ram_in = mem_in;
  380. a->ram_inw = mem_inw;
  381. a->ram_in_buffer = mem_in_buffer;
  382. a->ram_look_ahead = mem_look_ahead;
  383. a->ram_out = mem_out;
  384. a->ram_outw = mem_outw;
  385. a->ram_out_buffer = mem_out_buffer;
  386. a->ram_inc = mem_inc;
  387. IoAdapter->out = pr_out;
  388. IoAdapter->dpc = pr_dpc;
  389. IoAdapter->tst_irq = scom_test_int;
  390. IoAdapter->clr_irq = scom_clear_int;
  391. IoAdapter->pcm = (struct pc_maint *)MIPS_MAINT_OFFS;
  392. IoAdapter->load = load_qBri_hardware;
  393. IoAdapter->disIrq = disable_qBri_interrupt;
  394. IoAdapter->rstFnc = reset_qBri_hardware;
  395. IoAdapter->stop = stop_qBri_hardware;
  396. IoAdapter->trapFnc = qBri_cpu_trapped;
  397. IoAdapter->diva_isr_handler = qBri_ISR;
  398. IoAdapter->a.io = (void *)IoAdapter;
  399. }
  400. static void set_qBri_functions(PISDN_ADAPTER IoAdapter) {
  401. if (!IoAdapter->tasks) {
  402. IoAdapter->tasks = MQ_INSTANCE_COUNT;
  403. }
  404. IoAdapter->MemorySize = MQ_MEMORY_SIZE;
  405. set_common_qBri_functions(IoAdapter);
  406. diva_os_set_qBri_functions(IoAdapter);
  407. }
  408. static void set_qBri2_functions(PISDN_ADAPTER IoAdapter) {
  409. if (!IoAdapter->tasks) {
  410. IoAdapter->tasks = MQ_INSTANCE_COUNT;
  411. }
  412. IoAdapter->MemorySize = (IoAdapter->tasks == 1) ? BRI2_MEMORY_SIZE : MQ2_MEMORY_SIZE;
  413. set_common_qBri_functions(IoAdapter);
  414. diva_os_set_qBri2_functions(IoAdapter);
  415. }
  416. /******************************************************************************/
  417. void prepare_qBri_functions(PISDN_ADAPTER IoAdapter) {
  418. set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[0]);
  419. set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[1]);
  420. set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[2]);
  421. set_qBri_functions(IoAdapter->QuadroList->QuadroAdapter[3]);
  422. }
  423. void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter) {
  424. if (!IoAdapter->tasks) {
  425. IoAdapter->tasks = MQ_INSTANCE_COUNT;
  426. }
  427. set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[0]);
  428. if (IoAdapter->tasks > 1) {
  429. set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[1]);
  430. set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[2]);
  431. set_qBri2_functions(IoAdapter->QuadroList->QuadroAdapter[3]);
  432. }
  433. }
  434. /* -------------------------------------------------------------------------- */