patch-2.1.101 linux/arch/sparc64/kernel/psycho.c
Next file: linux/arch/sparc64/kernel/ptrace.c
Previous file: linux/arch/sparc64/kernel/process.c
Back to the patch index
Back to the overall index
- Lines: 492
- Date:
Fri May 8 00:11:29 1998
- Orig file:
v2.1.100/linux/arch/sparc64/kernel/psycho.c
- Orig date:
Thu May 7 22:51:47 1998
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.50 1998/04/10 12:29:47 ecd Exp $
+/* $Id: psycho.c,v 1.54 1998/05/01 19:16:32 ecd Exp $
* psycho.c: Ultra/AX U2P PCI controller support.
*
* Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -9,6 +9,8 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
#include <asm/ebus.h>
#include <asm/sbus.h> /* for sanity check... */
@@ -17,6 +19,7 @@
#undef FIXUP_REGS_DEBUG
#undef FIXUP_IRQ_DEBUG
#undef FIXUP_VMA_DEBUG
+#undef PCI_COOKIE_DEBUG
#ifdef PROM_DEBUG
#define dprintf prom_printf
@@ -94,19 +97,12 @@
*/
static int pci_probe_enable = 0;
-static inline unsigned long long_align(unsigned long addr)
+__initfunc(static void psycho_iommu_init(struct linux_psycho *psycho, int tsbsize))
{
- return ((addr + (sizeof(unsigned long) - 1)) &
- ~(sizeof(unsigned long) - 1));
-}
-
-__initfunc(static unsigned long psycho_iommu_init(struct linux_psycho *psycho,
- int tsbsize,
- unsigned long memory_start))
-{
- unsigned long tsbbase = PAGE_ALIGN(memory_start);
+ unsigned long tsbbase;
unsigned long control, i;
unsigned long *iopte;
+ unsigned long order;
/*
* Invalidate TLB Entries.
@@ -120,9 +116,12 @@
control &= ~(IOMMU_CTRL_DENAB);
psycho->psycho_regs->iommu_control = control;
- memory_start = (tsbbase + ((tsbsize * 1024) * 8));
+ for(order = 0;; order++) {
+ if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
+ break;
+ }
+ tsbbase = __get_free_pages(GFP_DMA, order);
iopte = (unsigned long *)tsbbase;
-
for(i = 0; i < (tsbsize * 1024); i++) {
*iopte = (IOPTE_VALID | IOPTE_64K |
IOPTE_CACHE | IOPTE_WRITE);
@@ -154,8 +153,6 @@
break;
}
psycho->psycho_regs->iommu_control = control;
-
- return memory_start;
}
extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm);
@@ -164,7 +161,7 @@
/*
* Poor man's PCI...
*/
-__initfunc(unsigned long sabre_init(int pnode, unsigned long memory_start))
+__initfunc(void sabre_init(int pnode))
{
struct linux_prom64_registers pr_regs[2];
struct linux_psycho *sabre;
@@ -175,8 +172,7 @@
u32 portid;
int bus;
- sabre = (struct linux_psycho *)memory_start;
- memory_start = long_align(memory_start + sizeof(struct linux_psycho));
+ sabre = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
portid = prom_getintdefault(pnode, "upa-portid", 0xff);
@@ -262,7 +258,7 @@
prom_halt();
}
- memory_start = psycho_iommu_init(sabre, tsbsize, memory_start);
+ psycho_iommu_init(sabre, tsbsize);
pci_dvma_offset = vdma[0];
printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
@@ -338,11 +334,15 @@
if (!node)
break;
}
+}
- return memory_start;
+static __inline__ int
+apb_present(struct linux_psycho *psycho)
+{
+ return psycho->pci_bus ? 1 : 0;
}
-__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void pcibios_init(void))
{
struct linux_prom64_registers pr_regs[3];
struct linux_psycho *psycho;
@@ -355,7 +355,6 @@
dprintf("PCI: Probing for controllers.\n");
#endif
- memory_start = long_align(memory_start);
node = prom_getchild(prom_root_node);
while((node = prom_searchsiblings(node, "pci")) != 0) {
struct linux_psycho *search;
@@ -365,11 +364,11 @@
err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
if ((err > 0) && !strncmp(namebuf, "SUNW,sabre", err)) {
- memory_start = sabre_init(node, memory_start);
+ sabre_init(node);
goto next_pci;
}
- psycho = (struct linux_psycho *)memory_start;
+ psycho = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
portid = prom_getintdefault(node, "upa-portid", 0xff);
for(search = psycho_root; search; search = search->next) {
@@ -385,9 +384,6 @@
}
}
- memory_start = long_align(memory_start +
- sizeof(struct linux_psycho));
-
memset(psycho, 0, sizeof(*psycho));
psycho->next = psycho_root;
@@ -452,7 +448,7 @@
psycho->pci_config_space);
#endif
- memory_start = psycho_iommu_init(psycho, 32, memory_start);
+ psycho_iommu_init(psycho, 32);
pci_dvma_offset = 0x80000000UL;
is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
@@ -504,14 +500,11 @@
prom_halt();
}
- psycho_index_map = (struct linux_psycho **)long_align(memory_start);
- memory_start = long_align(memory_start + linux_num_psycho
- * sizeof(struct linux_psycho *));
+ psycho_index_map = kmalloc(sizeof(struct linux_psycho *) * linux_num_psycho,
+ GFP_ATOMIC);
for (psycho = psycho_root; psycho; psycho = psycho->next)
psycho_index_map[psycho->index] = psycho;
-
- return memory_start;
}
int pcibios_present(void)
@@ -577,40 +570,14 @@
}
}
-static unsigned long *pci_alloc_arena = NULL;
-
-static inline void pci_init_alloc_init(unsigned long *mstart)
-{
- pci_alloc_arena = mstart;
-}
-
-static inline void pci_init_alloc_fini(void)
-{
- pci_alloc_arena = NULL;
-}
-
-__initfunc(static void *pci_init_alloc(int size))
-{
- unsigned long start = long_align(*pci_alloc_arena);
- void *mp = (void *)start;
-
- if(!pci_alloc_arena) {
- prom_printf("pci_init_alloc: pci_vma arena not init'd\n");
- prom_halt();
- }
- start += size;
- *pci_alloc_arena = start;
- return mp;
-}
-
static inline struct pci_vma *pci_vma_alloc(void)
{
- return pci_init_alloc(sizeof(struct pci_vma));
+ return kmalloc(sizeof(struct pci_vma), GFP_ATOMIC);
}
static inline struct pcidev_cookie *pci_devcookie_alloc(void)
{
- return pci_init_alloc(sizeof(struct pcidev_cookie));
+ return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
}
@@ -694,6 +661,14 @@
unsigned short stmp;
unsigned int itmp;
+ for(pdev = pci_devices; pdev; pdev = pdev->next) {
+ if(pdev->vendor == PCI_VENDOR_ID_SUN &&
+ pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
+ /* Increase latency timer on top level bridge. */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8);
+ break;
+ }
+ }
for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -732,12 +707,14 @@
pci_write_config_byte(pdev, APB_PIO_TARGET_LATENCY_TIMER, 0);
pci_write_config_byte(pdev, APB_DMA_TARGET_RETRY_LIMIT, 0x80);
pci_write_config_byte(pdev, APB_DMA_TARGET_LATENCY_TIMER, 0);
+
+ /* Increase primary latency timer. */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8);
}
}
}
-__initfunc(static void sabre_probe(struct linux_psycho *sabre,
- unsigned long *mstart))
+__initfunc(static void sabre_probe(struct linux_psycho *sabre))
{
struct pci_bus *pbus = sabre->pci_bus;
static unsigned char busno = 0;
@@ -745,7 +722,7 @@
pbus->number = pbus->secondary = busno;
pbus->sysdata = sabre;
- pbus->subordinate = pci_scan_bus(pbus, mstart);
+ pbus->subordinate = pci_scan_bus(pbus);
busno = pbus->subordinate + 1;
for(pbus = pbus->children; pbus; pbus = pbus->next) {
@@ -759,8 +736,7 @@
}
-__initfunc(static void pbm_probe(struct linux_pbm_info *pbm,
- unsigned long *mstart))
+__initfunc(static void pbm_probe(struct linux_pbm_info *pbm))
{
static struct pci_bus *pchain = NULL;
struct pci_bus *pbus = &pbm->pci_bus;
@@ -777,7 +753,7 @@
pbm_fixup_busno(pbm, busno);
- pbus->subordinate = pci_scan_bus(pbus, mstart);
+ pbus->subordinate = pci_scan_bus(pbus);
/*
* Set the maximum subordinate bus of this pbm.
@@ -842,6 +818,10 @@
pcp->pbm = pbm;
pcp->prom_node = node;
pdev->sysdata = pcp;
+#ifdef PCI_COOKIE_DEBUG
+ dprintf("pdev_cookie_fillin: pdev [%02x.%02x]: pbm %p, node %x\n",
+ pdev->bus->number, pdev->devfn, pbm, node);
+#endif
}
__initfunc(static void fill_in_pbm_cookies(struct pci_bus *pbus,
@@ -851,6 +831,11 @@
pbus->sysdata = pbm;
+#ifdef PCI_COOKIE_DEBUG
+ dprintf("fill_in_pbm_cookies: pbus [%02x]: pbm %p\n",
+ pbus->number, pbm);
+#endif
+
for(pdev = pbus->devices; pdev; pdev = pdev->sibling)
pdev_cookie_fillin(pbm, pdev);
@@ -973,7 +958,7 @@
{
struct pci_vma *vp;
- if (pbm->parent->pci_bus) {
+ if (apb_present(pbm->parent)) {
/*
* Disallow anything that is not in our IO/MEM map on SIMBA.
*/
@@ -984,12 +969,8 @@
for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
struct pcidev_cookie *pcp = pdev->sysdata;
- if (!pcp) {
- prom_printf("record_assignments: "
- "no pcidev_cookie for pdev %02x\n",
- pdev->devfn);
- prom_halt();
- }
+ if (!pcp)
+ continue;
if (pcp->pbm == pbm)
break;
}
@@ -1448,9 +1429,12 @@
}
/* Exported for EBUS probing layer. */
-__initfunc(unsigned int psycho_irq_build(struct linux_pbm_info *pbm, unsigned int full_ino))
+__initfunc(unsigned int psycho_irq_build(struct linux_pbm_info *pbm,
+ struct pci_dev *pdev,
+ unsigned int full_ino))
{
unsigned long imap_off, ign, ino;
+ int need_dma_sync = 0;
ign = (full_ino & PSYCHO_IMAP_IGN) >> 6;
ino = (full_ino & PSYCHO_IMAP_INO);
@@ -1540,7 +1524,11 @@
}
imap_off -= imap_offset(imap_a_slot0);
- return pci_irq_encode(imap_off, pbm->parent->index, ign, ino);
+ if (apb_present(pbm->parent) && (pdev->bus->number != pbm->pci_first_busno)) {
+ need_dma_sync = 1;
+ }
+
+ return pci_irq_encode(imap_off, pbm->parent->index, ign, ino, need_dma_sync);
}
__initfunc(static int pbm_intmap_match(struct linux_pbm_info *pbm,
@@ -1618,7 +1606,7 @@
/* See if we find a matching interrupt-map entry. */
if (pbm_intmap_match(pbm, pdev, preg, &prom_irq)) {
- pdev->irq = psycho_irq_build(pbm,
+ pdev->irq = psycho_irq_build(pbm, pdev,
(pbm->parent->upa_portid << 6)
| prom_irq);
#ifdef FIXUP_IRQ_DEBUG
@@ -1627,14 +1615,14 @@
#endif
/* See if fully specified already (ie. for onboard devices like hme) */
} else if(((prom_irq & PSYCHO_IMAP_IGN) >> 6) == pbm->parent->upa_portid) {
- pdev->irq = psycho_irq_build(pbm, prom_irq);
+ pdev->irq = psycho_irq_build(pbm, pdev, prom_irq);
#ifdef FIXUP_IRQ_DEBUG
dprintf("fully specified prom_irq[%x] pdev->irq[%x]",
prom_irq, pdev->irq);
#endif
/* See if onboard device interrupt (i.e. bit 5 set) */
} else if((prom_irq & PSYCHO_IMAP_INO) & 0x20) {
- pdev->irq = psycho_irq_build(pbm,
+ pdev->irq = psycho_irq_build(pbm, pdev,
(pbm->parent->upa_portid << 6)
| prom_irq);
#ifdef FIXUP_IRQ_DEBUG
@@ -1669,7 +1657,7 @@
}
slot = (slot << 2);
- pdev->irq = psycho_irq_build(pbm,
+ pdev->irq = psycho_irq_build(pbm, pdev,
(((portid << 6) & PSYCHO_IMAP_IGN)
| (bus | slot | line)));
@@ -1818,7 +1806,7 @@
fixup_addr_irq(&psycho->pbm_B);
}
-__initfunc(unsigned long pcibios_fixup(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void pcibios_fixup(void))
{
struct linux_psycho *psycho;
@@ -1838,26 +1826,24 @@
for (psycho = psycho_root; psycho; psycho = psycho->next) {
/* Probe bus on builtin PCI. */
- if (psycho->pci_bus)
- sabre_probe(psycho, &memory_start);
+ if (apb_present(psycho))
+ sabre_probe(psycho);
else {
/* Probe busses under PBM B. */
- pbm_probe(&psycho->pbm_B, &memory_start);
+ pbm_probe(&psycho->pbm_B);
/* Probe busses under PBM A. */
- pbm_probe(&psycho->pbm_A, &memory_start);
+ pbm_probe(&psycho->pbm_A);
}
}
- pci_init_alloc_init(&memory_start);
-
/* Walk all PCI devices found. For each device, and
* PCI bridge which is not one of the PSYCHO PBM's, fill in the
* sysdata with a pointer to the PBM (for pci_bus's) or
* a pci_dev cookie (PBM+PROM_NODE, for pci_dev's).
*/
for (psycho = psycho_root; psycho; psycho = psycho->next) {
- if (psycho->pci_bus)
+ if (apb_present(psycho))
sabre_cookie_fillin(psycho);
fill_in_pbm_cookies(&psycho->pbm_A.pci_bus,
@@ -1873,9 +1859,7 @@
psycho_final_fixup(psycho);
}
- pci_init_alloc_fini();
-
- return ebus_init(memory_start, memory_end);
+ return ebus_init();
}
/* "PCI: The emerging standard..." 8-( */
@@ -2257,7 +2241,7 @@
{
struct linux_pbm_info *pbm = bus2pbm[bus];
- if (pbm && pbm->parent && pbm->parent->pci_bus)
+ if (pbm && pbm->parent && apb_present(pbm->parent))
return sabre_read_config_byte(pbm, bus, devfn, where, value);
return pbm_read_config_byte(pbm, bus, devfn, where, value);
}
@@ -2267,7 +2251,7 @@
{
struct linux_pbm_info *pbm = bus2pbm[bus];
- if (pbm && pbm->parent && pbm->parent->pci_bus)
+ if (pbm && pbm->parent && apb_present(pbm->parent))
return sabre_read_config_word(pbm, bus, devfn, where, value);
return pbm_read_config_word(pbm, bus, devfn, where, value);
}
@@ -2277,7 +2261,7 @@
{
struct linux_pbm_info *pbm = bus2pbm[bus];
- if (pbm && pbm->parent && pbm->parent->pci_bus)
+ if (pbm && pbm->parent && apb_present(pbm->parent))
return sabre_read_config_dword(pbm, bus, devfn, where, value);
return pbm_read_config_dword(pbm, bus, devfn, where, value);
}
@@ -2287,7 +2271,7 @@
{
struct linux_pbm_info *pbm = bus2pbm[bus];
- if (pbm && pbm->parent && pbm->parent->pci_bus)
+ if (pbm && pbm->parent && apb_present(pbm->parent))
return sabre_write_config_byte(pbm, bus, devfn, where, value);
return pbm_write_config_byte(pbm, bus, devfn, where, value);
}
@@ -2297,7 +2281,7 @@
{
struct linux_pbm_info *pbm = bus2pbm[bus];
- if (pbm && pbm->parent && pbm->parent->pci_bus)
+ if (pbm && pbm->parent && apb_present(pbm->parent))
return sabre_write_config_word(pbm, bus, devfn, where, value);
return pbm_write_config_word(bus2pbm[bus], bus, devfn, where, value);
}
@@ -2307,7 +2291,7 @@
{
struct linux_pbm_info *pbm = bus2pbm[bus];
- if (pbm && pbm->parent && pbm->parent->pci_bus)
+ if (pbm && pbm->parent && apb_present(pbm->parent))
return sabre_write_config_dword(pbm, bus, devfn, where, value);
return pbm_write_config_dword(bus2pbm[bus], bus, devfn, where, value);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov