1 /*
2 * Copyright (C) Eicon Technology Corporation, 2000.
3 *
4 * Eicon File Revision : 1.16
5 *
6 * This software may be used and distributed according to the terms
7 * of the GNU General Public License, incorporated herein by reference.
8 *
9 */
10
11 #define N_DATA
12
13 #include <asm/io.h>
14 #include <asm/system.h>
15 #include <linux/slab.h>
16 #include <linux/pci.h>
17 #include <linux/delay.h>
18 #undef N_DATA
19
20 #include "uxio.h"
21
22 static
23 int log_on=0;
24
25 int Divasdevflag = 0;
26
27 //spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
28
29 static
30 ux_diva_card_t card_pool[MAX_CARDS];
31
UxPause(long int ms)32 void UxPause(long int ms)
33 {
34 int timeout = jiffies + ((ms * HZ) / 1000);
35
36 while (time_before(jiffies, timeout));
37 }
38
UxCardHandleGet(ux_diva_card_t ** card,dia_card_t * cfg)39 int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
40 {
41 int i;
42 ux_diva_card_t *c;
43
44 if (cfg->bus_type != DIA_BUS_TYPE_PCI)
45 {
46 DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
47 return -1;
48 }
49
50 for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
51 {
52 ;
53 }
54
55 if (i == DIM(card_pool))
56 {
57 DPRINTF(("divas hw: card_pool exhausted"));
58 return -1;
59 }
60
61 c = *card = &card_pool[i];
62
63 switch (cfg->bus_type)
64 {
65 case DIA_BUS_TYPE_PCI:
66 c->bus_num = cfg->bus_num;
67 c->func_num = cfg->func_num;
68 c->io_base = cfg->io_base;
69 c->reset_base = cfg->reset_base;
70 c->card_type = cfg->card_type;
71 c->mapped = NULL;
72 c->slot = cfg->slot;
73 c->irq = (int) cfg->irq;
74 c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
75 c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
76 c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
77 c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
78 c->pCONTROL = cfg->memory[DIVAS_CTL_MEMORY];
79
80 /* c->bus_type = DIA_BUS_TYPE_PCI;
81 c->bus_num = cfg->bus_num & 0x3f;
82 c->slot = cfg->slot;
83 c->irq = (int) cfg->irq;
84 c->int_priority = (int) cfg->int_priority;
85 c->card_type = cfg->card_type;
86 c->io_base = cfg->io_base;
87 c->reset_base = cfg->reset_base;
88 c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
89 c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
90 c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
91 c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
92 DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
93 DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
94 DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
95 c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/
96 break;
97 default:
98 break;
99 }
100
101 c->in_use = TRUE;
102
103 return 0;
104 }
105
UxCardHandleFree(ux_diva_card_t * card)106 void UxCardHandleFree(ux_diva_card_t *card)
107 {
108 card->in_use = FALSE;
109 }
110
111
112 #define PLX_IOBASE 0
113 #define DIVAS_IOBASE 1
UxCardMemAttach(ux_diva_card_t * card,int id)114 void *UxCardMemAttach(ux_diva_card_t *card, int id)
115 {
116 if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
117 {
118 switch (id)
119 {
120 case DIVAS_SHARED_MEMORY:
121 card->mapped = card->pSHARED;
122 return card->pSHARED;
123 break;
124 case DIVAS_RAM_MEMORY:
125 card->mapped = card->pDRAM;
126 return card->pDRAM;
127 break;
128 case DIVAS_REG_MEMORY:
129 card->mapped = card->pDEVICES;
130 return card->pDEVICES;
131 break;
132 case DIVAS_CFG_MEMORY:
133 card->mapped = card->pCONFIG;
134 return card->pCONFIG;
135 break;
136 default:
137 ASSERT(FALSE);
138 card->mapped = NULL;
139 return (void *) 0;
140 }
141 }
142 else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
143 {
144 switch (id)
145 {
146 case PLX_IOBASE:
147 return (void *) card->reset_base;
148 break;
149 case DIVAS_IOBASE:
150 return (void *) card->io_base;
151 break;
152 default:
153 ASSERT(FALSE);
154 return 0;
155 }
156 }
157
158 else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
159 {
160 switch (id)
161 {
162 case DIVAS_SHARED_MEMORY:
163 card->mapped = card->pSHARED;
164 return card->pSHARED;
165 break;
166 case DIVAS_RAM_MEMORY:
167 card->mapped = card->pDRAM;
168 return card->pDRAM;
169 break;
170 case DIVAS_REG_MEMORY:
171 card->mapped = (void *) card->io_base;
172 return (void *) card->io_base;
173 break;
174 case DIVAS_CTL_MEMORY:
175 card->mapped = card->pCONTROL;
176 return card->pCONTROL;
177 break;
178 default:
179 // ASSERT(FALSE);
180 DPRINTF(("divas: Trying to attach to mem %d", id));
181 card->mapped = NULL;
182 return (void *) 0;
183 }
184 } else
185 DPRINTF(("divas: Tried to attach to unknown card"));
186
187 /* Unknown card type */
188 return NULL;
189 }
190
UxCardMemDetach(ux_diva_card_t * card,void * address)191 void UxCardMemDetach(ux_diva_card_t *card, void *address)
192 {
193 return; // Just a place holder. No un-mapping done.
194 }
195
UxCardLog(int turn_on)196 void UxCardLog(int turn_on)
197 {
198 log_on = turn_on;
199 }
200
201 /*
202 * Control Register I/O Routines to be performed on Attached I/O ports
203 */
204
UxCardPortIoOut(ux_diva_card_t * card,void * AttachedBase,int offset,byte the_byte)205 void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
206 {
207 word base = (word) (dword) AttachedBase;
208
209 base += offset;
210
211 outb(the_byte, base);
212 }
213
UxCardPortIoOutW(ux_diva_card_t * card,void * AttachedBase,int offset,word the_word)214 void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
215 {
216 word base = (word) (dword) AttachedBase;
217
218 base += offset;
219
220 outw(the_word, base);
221 }
222
UxCardPortIoOutD(ux_diva_card_t * card,void * AttachedBase,int offset,dword the_dword)223 void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
224 {
225 word base = (word) (dword) AttachedBase;
226
227 base += offset;
228
229 outl(the_dword, base);
230 }
231
UxCardPortIoIn(ux_diva_card_t * card,void * AttachedBase,int offset)232 byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
233 {
234 word base = (word) (dword) AttachedBase;
235
236 base += offset;
237
238 return inb(base);
239 }
240
UxCardPortIoInW(ux_diva_card_t * card,void * AttachedBase,int offset)241 word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
242 {
243 word base = (word) (dword) AttachedBase;
244
245 base += offset;
246
247 return inw(base);
248 }
249
250 /*
251 * Memory mapped card I/O functions
252 */
253
UxCardMemIn(ux_diva_card_t * card,void * address)254 byte UxCardMemIn(ux_diva_card_t *card, void *address)
255 {
256 byte b;
257 volatile byte* t = (byte*)address;
258
259 b = *t;
260
261 if (log_on)
262 {
263 byte *a = address;
264 a -= (int) card->mapped;
265 DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
266 }
267
268 return(b);
269 }
270
UxCardMemInW(ux_diva_card_t * card,void * address)271 word UxCardMemInW(ux_diva_card_t *card, void *address)
272 {
273 word w;
274 volatile word* t = (word*)address;
275
276 w = *t;
277
278 if (log_on)
279 {
280 byte *a = address;
281 a -= (int) card->mapped;
282 DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
283 }
284
285 return (w);
286 }
287
UxCardMemInD(ux_diva_card_t * card,void * address)288 dword UxCardMemInD(ux_diva_card_t *card, void *address)
289 {
290 dword dw;
291 volatile dword* t = (dword*)address;
292
293 dw = *t;
294
295 if (log_on)
296 {
297 byte *a = address;
298 a -= (int) card->mapped;
299 DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
300 }
301
302 return (dw);
303 }
304
UxCardMemInBuffer(ux_diva_card_t * card,void * address,void * buffer,int length)305 void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
306 {
307 volatile byte *pSource = address;
308 byte *pDest = buffer;
309
310 while (length--)
311 {
312 *pDest++ = *pSource++;
313 }
314
315 if (log_on)
316 {
317 byte *a = address;
318 a -= (int) card->mapped;
319 pDest = buffer;
320 DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)",
321 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
322 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
323 a));
324 }
325
326 return;
327 }
328
UxCardMemOut(ux_diva_card_t * card,void * address,byte data)329 void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
330 {
331 volatile byte* t = (byte*)address;
332
333 if (log_on)
334 {
335 byte *a = address;
336 a -= (int) card->mapped;
337 DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
338 }
339
340 *t = data;
341
342 return;
343 }
344
UxCardMemOutW(ux_diva_card_t * card,void * address,word data)345 void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
346 {
347 volatile word* t = (word*)address;
348
349 if (log_on)
350 {
351 byte *a = address;
352 a -= (int) card->mapped;
353 DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
354 }
355
356 *t = data;
357 return;
358 }
359
UxCardMemOutD(ux_diva_card_t * card,void * address,dword data)360 void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
361 {
362 volatile dword* t = (dword*)address;
363
364 if (log_on)
365 {
366 byte *a = address;
367 a -= (int) card->mapped;
368 DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
369 }
370
371 *t = data;
372 return;
373 }
374
UxCardMemOutBuffer(ux_diva_card_t * card,void * address,void * buffer,int length)375 void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
376 {
377 byte *pSource = buffer;
378 byte *pDest = address;
379
380 while (length--)
381 {
382 *pDest++ = *pSource++;
383 }
384
385 if (log_on)
386 {
387 byte *a = address;
388 a -= (int) card->mapped;
389 pDest = buffer;
390 DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)",
391 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
392 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
393 a));
394 }
395
396 return;
397 }
398
399 /*
400 * Memory mapped card I/O functions
401 */
402
UxCardIoIn(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address)403 byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
404
405 {
406 byte the_byte;
407
408 outb(0xFF, card->io_base + 0xC);
409 outw((word) (dword) address, card->io_base + 4);
410
411 the_byte = inb(card->io_base);
412
413 if (log_on)
414 {
415 DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)",
416 the_byte & 0xff, address));
417 }
418
419 return the_byte;
420 }
421
UxCardIoInW(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address)422 word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
423
424 {
425 word the_word;
426
427 outb(0xFF, card->io_base + 0xC);
428 outw((word) (dword) address, card->io_base + 4);
429 the_word = inw(card->io_base);
430
431 if (log_on)
432 {
433 DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)",
434 the_word & 0xffff, address));
435 }
436
437 return the_word;
438 }
439
UxCardIoInD(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address)440 dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
441
442 {
443 dword the_dword;
444
445 outb(0xFF, card->io_base + 0xC);
446 outw((word) (dword) address, card->io_base + 4);
447 the_dword = inl(card->io_base);
448
449 if (log_on)
450 {
451 DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)",
452 the_dword, address));
453 }
454
455 return the_dword;
456 }
457
UxCardIoInBuffer(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address,void * buffer,int length)458 void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
459
460 {
461 byte *pSource = address;
462 byte *pDest = buffer;
463
464 if ((word) (dword) address & 0x1)
465 {
466 outb(0xFF, card->io_base + 0xC);
467 outw((word) (dword) pSource, card->io_base + 4);
468 *pDest = (byte) inb(card->io_base);
469 pDest++;
470 pSource++;
471 length--;
472 if (!length)
473 {
474 return;
475 }
476 }
477
478 outb(0xFF, card->io_base + 0xC);
479 outw((word) (dword) pSource, card->io_base + 4);
480 insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
481
482 if (log_on)
483 {
484 pDest = buffer;
485 DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)",
486 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
487 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
488 address));
489 }
490
491 return;
492 }
493
494 /* Output */
495
UxCardIoOut(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address,byte data)496 void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
497 {
498 if (log_on)
499 {
500 DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)",
501 data & 0xff, address));
502 }
503
504 outb(0xFF, card->io_base + 0xC);
505 outw((word) (dword) address, card->io_base + 4);
506 outb((byte) data & 0xFF, card->io_base);
507
508 return;
509 }
510
UxCardIoOutW(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address,word data)511 void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
512 {
513 if (log_on)
514 {
515 DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)",
516 data & 0xffff, address));
517 }
518
519 outb(0xFF, card->io_base + 0xC);
520 outw((word) (dword) address, card->io_base + 4);
521 outw((word) data & 0xFFFF, card->io_base);
522
523 return;
524 }
525
UxCardIoOutD(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address,dword data)526 void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
527 {
528 if (log_on)
529 {
530 DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
531 }
532
533 outb(0xFF, card->io_base + 0xC);
534 outw((word) (dword) address, card->io_base + 4);
535 outl((dword) data & 0xFFFFFFFF, card->io_base);
536
537 return;
538 }
539
UxCardIoOutBuffer(ux_diva_card_t * card,void * AttachedDivasIOBase,void * address,void * buffer,int length)540 void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
541
542 {
543 byte *pSource = buffer;
544 byte *pDest = address;
545
546 if ((word) (dword) address & 1)
547 {
548 outb(0xFF, card->io_base + 0xC);
549 outw((word) (dword) pDest, card->io_base + 4);
550 outb(*pSource, card->io_base);
551 pSource++;
552 pDest++;
553 length--;
554 if (!length)
555 {
556 return;
557 }
558 }
559
560 outb(0xFF, card->io_base + 0xC);
561 outw((word) (dword) pDest, card->io_base + 4);
562 outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
563
564 if (log_on)
565 {
566 pDest = buffer;
567 DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)",
568 pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
569 pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
570 address));
571 }
572
573 return;
574 }
575
Divasintr(int arg,void * unused,struct pt_regs * unused_regs)576 void Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
577 {
578 int i;
579 card_t *card = NULL;
580 ux_diva_card_t *ux_ref = NULL;
581
582 for (i = 0; i < DivasCardNext; i++)
583 {
584
585 if (arg == DivasCards[i].cfg.irq)
586 {
587 card = &DivasCards[i];
588 ux_ref = card->hw;
589
590 if ((ux_ref) && (card->is_live))
591 {
592 (*ux_ref->user_isr)(ux_ref->user_isr_arg);
593 }
594 else
595 {
596 DPRINTF(("divas: ISR couldn't locate card"));
597 }
598 }
599 }
600
601 return;
602 }
603
604
UxIsrInstall(ux_diva_card_t * card,isr_fn_t * isr_fn,void * isr_arg)605 int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
606 {
607 int result;
608
609 card->user_isr = isr_fn;
610 card->user_isr_arg = isr_arg;
611
612 result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
613
614 return result;
615 }
616
UxIsrRemove(ux_diva_card_t * card,void * dev_id)617 void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
618 {
619 free_irq(card->irq, card->user_isr_arg);
620 }
621
UxPciConfigWrite(ux_diva_card_t * card,int size,int offset,void * value)622 void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
623 {
624 switch (size)
625 {
626 case sizeof(byte):
627 pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
628 break;
629 case sizeof(word):
630 pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
631 break;
632 case sizeof(dword):
633 pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
634 break;
635 default:
636 printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
637 }
638 }
639
UxPciConfigRead(ux_diva_card_t * card,int size,int offset,void * value)640 void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
641 {
642 switch (size)
643 {
644 case sizeof(byte):
645 pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
646 break;
647 case sizeof(word):
648 pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
649 break;
650 case sizeof(dword):
651 pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
652 break;
653 default:
654 printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
655 }
656 }
657
UxAlloc(unsigned int size)658 void *UxAlloc(unsigned int size)
659 {
660 void *m;
661
662 m = kmalloc(size, GFP_ATOMIC);
663
664 return m;
665 }
666
UxFree(void * ptr)667 void UxFree(void *ptr)
668 {
669 kfree(ptr);
670 }
671
UxCardLock(ux_diva_card_t * card)672 long UxCardLock(ux_diva_card_t *card)
673 {
674 unsigned long flags;
675
676 //spin_lock_irqsave(&diva_lock, flags);
677
678 save_flags(flags);
679 cli();
680 return flags;
681
682 }
683
UxCardUnlock(ux_diva_card_t * card,long ipl)684 void UxCardUnlock(ux_diva_card_t *card, long ipl)
685 {
686 //spin_unlock_irqrestore(&diva_lock, ipl);
687
688 restore_flags(ipl);
689
690 }
691
UxTimeGet(void)692 dword UxTimeGet(void)
693 {
694 return jiffies;
695 }
696
UxInterlockedIncrement(ux_diva_card_t * card,long * dst)697 long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
698 {
699 register volatile long *p;
700 register long ret;
701 int ipl;
702
703 p =dst;
704
705 ipl = UxCardLock(card);
706
707 *p += 1;
708 ret = *p;
709
710 UxCardUnlock(card,ipl);
711
712 return(ret);
713
714 }
715
UxInterlockedDecrement(ux_diva_card_t * card,long * dst)716 long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
717 {
718 register volatile long *p;
719 register long ret;
720 int ipl;
721
722 p =dst;
723
724 ipl = UxCardLock(card);
725
726 *p -= 1;
727 ret = *p;
728
729 UxCardUnlock(card,ipl);
730
731 return(ret);
732
733 }
734