Viewing file: linio.c (14.36 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* * Copyright (C) Eicon Technology Corporation, 2000. * * Eicon File Revision : 1.16 * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */
#define N_DATA
#include <asm/io.h> #include <asm/system.h> #include <linux/slab.h> #include <linux/pci.h> #include <linux/delay.h> #undef N_DATA
#include "uxio.h"
static int log_on=0;
int Divasdevflag = 0;
//spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
static ux_diva_card_t card_pool[MAX_CARDS];
void UxPause(long int ms) { int timeout = jiffies + ((ms * HZ) / 1000);
while (time_before(jiffies, timeout)); }
int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg) { int i; ux_diva_card_t *c;
if (cfg->bus_type != DIA_BUS_TYPE_PCI) { DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type)); return -1; }
for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++) { ; }
if (i == DIM(card_pool)) { DPRINTF(("divas hw: card_pool exhausted")); return -1; }
c = *card = &card_pool[i];
switch (cfg->bus_type) { case DIA_BUS_TYPE_PCI: c->bus_num = cfg->bus_num; c->func_num = cfg->func_num; c->io_base = cfg->io_base; c->reset_base = cfg->reset_base; c->card_type = cfg->card_type; c->mapped = NULL; c->slot = cfg->slot; c->irq = (int) cfg->irq; c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY]; c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY]; c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY]; c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY]; c->pCONTROL = cfg->memory[DIVAS_CTL_MEMORY];
/* c->bus_type = DIA_BUS_TYPE_PCI; c->bus_num = cfg->bus_num & 0x3f; c->slot = cfg->slot; c->irq = (int) cfg->irq; c->int_priority = (int) cfg->int_priority; c->card_type = cfg->card_type; c->io_base = cfg->io_base; c->reset_base = cfg->reset_base; c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY]; c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY]; c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY]; c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY]; DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM)); DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED)); DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG)); c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/ break; default: break; }
c->in_use = TRUE;
return 0; }
void UxCardHandleFree(ux_diva_card_t *card) { card->in_use = FALSE; }
#define PLX_IOBASE 0 #define DIVAS_IOBASE 1 void *UxCardMemAttach(ux_diva_card_t *card, int id) { if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER) { switch (id) { case DIVAS_SHARED_MEMORY: card->mapped = card->pSHARED; return card->pSHARED; break; case DIVAS_RAM_MEMORY: card->mapped = card->pDRAM; return card->pDRAM; break; case DIVAS_REG_MEMORY: card->mapped = card->pDEVICES; return card->pDEVICES; break; case DIVAS_CFG_MEMORY: card->mapped = card->pCONFIG; return card->pCONFIG; break; default: ASSERT(FALSE); card->mapped = NULL; return (void *) 0; } } else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B) { switch (id) { case PLX_IOBASE: return (void *) card->reset_base; break; case DIVAS_IOBASE: return (void *) card->io_base; break; default: ASSERT(FALSE); return 0; } } else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q) { switch (id) { case DIVAS_SHARED_MEMORY: card->mapped = card->pSHARED; return card->pSHARED; break; case DIVAS_RAM_MEMORY: card->mapped = card->pDRAM; return card->pDRAM; break; case DIVAS_REG_MEMORY: card->mapped = (void *) card->io_base; return (void *) card->io_base; break; case DIVAS_CTL_MEMORY: card->mapped = card->pCONTROL; return card->pCONTROL; break; default: // ASSERT(FALSE); DPRINTF(("divas: Trying to attach to mem %d", id)); card->mapped = NULL; return (void *) 0; } } else DPRINTF(("divas: Tried to attach to unknown card"));
/* Unknown card type */ return NULL; }
void UxCardMemDetach(ux_diva_card_t *card, void *address) { return; // Just a place holder. No un-mapping done. }
void UxCardLog(int turn_on) { log_on = turn_on; }
/* * Control Register I/O Routines to be performed on Attached I/O ports */
void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte) { word base = (word) (dword) AttachedBase;
base += offset;
outb(the_byte, base); }
void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word) { word base = (word) (dword) AttachedBase;
base += offset;
outw(the_word, base); }
void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword) { word base = (word) (dword) AttachedBase;
base += offset;
outl(the_dword, base); }
byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset) { word base = (word) (dword) AttachedBase;
base += offset;
return inb(base); }
word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset) { word base = (word) (dword) AttachedBase;
base += offset;
return inw(base); }
/* * Memory mapped card I/O functions */
byte UxCardMemIn(ux_diva_card_t *card, void *address) { byte b; volatile byte* t = (byte*)address;
b = *t;
if (log_on) { byte *a = address; a -= (int) card->mapped; DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a)); }
return(b); }
word UxCardMemInW(ux_diva_card_t *card, void *address) { word w; volatile word* t = (word*)address;
w = *t;
if (log_on) { byte *a = address; a -= (int) card->mapped; DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a)); }
return (w); }
dword UxCardMemInD(ux_diva_card_t *card, void *address) { dword dw; volatile dword* t = (dword*)address;
dw = *t;
if (log_on) { byte *a = address; a -= (int) card->mapped; DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a)); }
return (dw); }
void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length) { volatile byte *pSource = address; byte *pDest = buffer;
while (length--) { *pDest++ = *pSource++; }
if (log_on) { byte *a = address; a -= (int) card->mapped; pDest = buffer; DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)", pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff, pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff, a)); }
return; }
void UxCardMemOut(ux_diva_card_t *card, void *address, byte data) { volatile byte* t = (byte*)address;
if (log_on) { byte *a = address; a -= (int) card->mapped; DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a)); }
*t = data;
return; }
void UxCardMemOutW(ux_diva_card_t *card, void *address, word data) { volatile word* t = (word*)address;
if (log_on) { byte *a = address; a -= (int) card->mapped; DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a)); }
*t = data; return; }
void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data) { volatile dword* t = (dword*)address;
if (log_on) { byte *a = address; a -= (int) card->mapped; DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a)); }
*t = data; return; }
void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length) { byte *pSource = buffer; byte *pDest = address;
while (length--) { *pDest++ = *pSource++; }
if (log_on) { byte *a = address; a -= (int) card->mapped; pDest = buffer; DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)", pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff, pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff, a)); }
return; }
/* * Memory mapped card I/O functions */
byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{ byte the_byte;
outb(0xFF, card->io_base + 0xC); outw((word) (dword) address, card->io_base + 4);
the_byte = inb(card->io_base);
if (log_on) { DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)", the_byte & 0xff, address)); } return the_byte; }
word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{ word the_word;
outb(0xFF, card->io_base + 0xC); outw((word) (dword) address, card->io_base + 4); the_word = inw(card->io_base);
if (log_on) { DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)", the_word & 0xffff, address)); }
return the_word; }
dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{ dword the_dword;
outb(0xFF, card->io_base + 0xC); outw((word) (dword) address, card->io_base + 4); the_dword = inl(card->io_base);
if (log_on) { DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)", the_dword, address)); }
return the_dword; }
void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
{ byte *pSource = address; byte *pDest = buffer;
if ((word) (dword) address & 0x1) { outb(0xFF, card->io_base + 0xC); outw((word) (dword) pSource, card->io_base + 4); *pDest = (byte) inb(card->io_base); pDest++; pSource++; length--; if (!length) { return; } }
outb(0xFF, card->io_base + 0xC); outw((word) (dword) pSource, card->io_base + 4); insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
if (log_on) { pDest = buffer; DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)", pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff, pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff, address)); }
return; }
/* Output */
void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data) { if (log_on) { DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)", data & 0xff, address)); }
outb(0xFF, card->io_base + 0xC); outw((word) (dword) address, card->io_base + 4); outb((byte) data & 0xFF, card->io_base);
return; }
void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data) { if (log_on) { DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)", data & 0xffff, address)); }
outb(0xFF, card->io_base + 0xC); outw((word) (dword) address, card->io_base + 4); outw((word) data & 0xFFFF, card->io_base);
return; }
void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data) { if (log_on) { DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address)); }
outb(0xFF, card->io_base + 0xC); outw((word) (dword) address, card->io_base + 4); outl((dword) data & 0xFFFFFFFF, card->io_base);
return; }
void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
{ byte *pSource = buffer; byte *pDest = address;
if ((word) (dword) address & 1) { outb(0xFF, card->io_base + 0xC); outw((word) (dword) pDest, card->io_base + 4); outb(*pSource, card->io_base); pSource++; pDest++; length--; if (!length) { return; } }
outb(0xFF, card->io_base + 0xC); outw((word) (dword) pDest, card->io_base + 4); outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
if (log_on) { pDest = buffer; DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)", pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff, pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff, address)); }
return; }
void Divasintr(int arg, void *unused, struct pt_regs *unused_regs) { int i; card_t *card = NULL; ux_diva_card_t *ux_ref = NULL;
for (i = 0; i < DivasCardNext; i++) {
if (arg == DivasCards[i].cfg.irq) { card = &DivasCards[i]; ux_ref = card->hw; if ((ux_ref) && (card->is_live)) { (*ux_ref->user_isr)(ux_ref->user_isr_arg); } else { DPRINTF(("divas: ISR couldn't locate card")); } } }
return; }
int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg) { int result;
card->user_isr = isr_fn; card->user_isr_arg = isr_arg;
result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
return result; }
void UxIsrRemove(ux_diva_card_t *card, void *dev_id) { free_irq(card->irq, card->user_isr_arg); }
void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value) { switch (size) { case sizeof(byte): pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value); break; case sizeof(word): pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value); break; case sizeof(dword): pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value); break; default: printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n"); } }
void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value) { switch (size) { case sizeof(byte): pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value); break; case sizeof(word): pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value); break; case sizeof(dword): pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value); break; default: printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n"); } }
void *UxAlloc(unsigned int size) { void *m;
m = kmalloc(size, GFP_ATOMIC);
return m; }
void UxFree(void *ptr) { kfree(ptr); }
long UxCardLock(ux_diva_card_t *card) { unsigned long flags;
//spin_lock_irqsave(&diva_lock, flags); save_flags(flags); cli(); return flags; }
void UxCardUnlock(ux_diva_card_t *card, long ipl) { //spin_unlock_irqrestore(&diva_lock, ipl);
restore_flags(ipl);
}
dword UxTimeGet(void) { return jiffies; }
long UxInterlockedIncrement(ux_diva_card_t *card, long *dst) { register volatile long *p; register long ret; int ipl;
p =dst; ipl = UxCardLock(card);
*p += 1; ret = *p;
UxCardUnlock(card,ipl);
return(ret);
}
long UxInterlockedDecrement(ux_diva_card_t *card, long *dst) { register volatile long *p; register long ret; int ipl;
p =dst; ipl = UxCardLock(card);
*p -= 1; ret = *p;
UxCardUnlock(card,ipl);
return(ret);
}
|