diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-09-20 17:39:06 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-09-20 17:39:06 +0000 |
commit | 52af272e9459618b0ddbe7123c1a2431a1226e86 (patch) | |
tree | a5cae08988fd82fea51268e3f9cbe261a8bca67d /sys | |
parent | 7d56032c82fa70600a62adf0a833a2d84915f79a (diff) |
support 64bit BARs from NetBSD
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/pci_map.c | 62 | ||||
-rw-r--r-- | sys/dev/pci/pcireg.h | 10 |
2 files changed, 56 insertions, 16 deletions
diff --git a/sys/dev/pci/pci_map.c b/sys/dev/pci/pci_map.c index af1ed413ace..67e36544287 100644 --- a/sys/dev/pci/pci_map.c +++ b/sys/dev/pci/pci_map.c @@ -1,12 +1,12 @@ -/* $OpenBSD: pci_map.c,v 1.3 2000/06/09 16:09:09 chris Exp $ */ -/* $NetBSD: pci_map.c,v 1.5 1998/08/15 10:10:54 mycroft Exp $ */ +/* $OpenBSD: pci_map.c,v 1.4 2000/09/20 17:39:04 niklas Exp $ */ +/* $NetBSD: pci_map.c,v 1.7 2000/05/10 16:58:42 thorpej Exp $ */ /*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum. + * by Charles M. Hannum; by William R. Studenmund; by Jason R. Thorpe. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -117,11 +117,17 @@ nbsd_pci_mem_find(pc, tag, reg, type, basep, sizep, flagsp) bus_size_t *sizep; int *flagsp; { - pcireg_t address, mask; - int s; + pcireg_t address, mask, address1 = 0, mask1 = 0xffffffff; + u_int64_t waddress, wmask; + int s, is64bit; + + is64bit = (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT); if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) - panic("pci_find_mem: bad request"); + panic("pci_mem_find: bad request"); + + if (is64bit && (reg + 4) >= PCI_MAPREG_END) + panic("pci_mem_find: bad 64-bit request"); /* * Section 6.2.5.1, `Address Maps', tells us that: @@ -138,6 +144,12 @@ nbsd_pci_mem_find(pc, tag, reg, type, basep, sizep, flagsp) pci_conf_write(pc, tag, reg, 0xffffffff); mask = pci_conf_read(pc, tag, reg); pci_conf_write(pc, tag, reg, address); + if (is64bit) { + address1 = pci_conf_read(pc, tag, reg + 4); + pci_conf_write(pc, tag, reg + 4, 0xffffffff); + mask1 = pci_conf_read(pc, tag, reg + 4); + pci_conf_write(pc, tag, reg + 4, address1); + } splx(s); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) { @@ -152,7 +164,10 @@ nbsd_pci_mem_find(pc, tag, reg, type, basep, sizep, flagsp) return (1); } - if (PCI_MAPREG_MEM_SIZE(mask) == 0) { + waddress = (u_int64_t)address1 << 32UL | address; + wmask = (u_int64_t)mask1 << 32UL | mask; + + if (PCI_MAPREG_MEM64_SIZE(wmask) == 0) { printf("pci_mem_find: void region\n"); return (1); } @@ -162,17 +177,36 @@ nbsd_pci_mem_find(pc, tag, reg, type, basep, sizep, flagsp) case PCI_MAPREG_MEM_TYPE_32BIT_1M: break; case PCI_MAPREG_MEM_TYPE_64BIT: - printf("pci_mem_find: 64-bit memory mapping register\n"); - return (1); + /* + * Handle the case of a 64-bit memory register on a + * platform with 32-bit addressing. Make sure that + * the address assigned and the device's memory size + * fit in 32 bits. We implicitly assume that if + * bus_addr_t is 64-bit, then so is bus_size_t. + */ + if (sizeof(u_int64_t) > sizeof(bus_addr_t) && + (address1 != 0 || mask1 != 0xffffffff)) { + printf("pci_mem_find: 64-bit memory map which is " + "inaccessible on a 32-bit platform\n"); + return (1); + } + break; default: printf("pci_mem_find: reserved mapping register type\n"); return (1); } - if (basep != 0) - *basep = PCI_MAPREG_MEM_ADDR(address); - if (sizep != 0) - *sizep = PCI_MAPREG_MEM_SIZE(mask); + if (sizeof(u_int64_t) > sizeof(bus_addr_t)) { + if (basep != 0) + *basep = PCI_MAPREG_MEM_ADDR(address); + if (sizep != 0) + *sizep = PCI_MAPREG_MEM_SIZE(mask); + } else { + if (basep != 0) + *basep = PCI_MAPREG_MEM64_ADDR(waddress); + if (sizep != 0) + *sizep = PCI_MAPREG_MEM64_SIZE(wmask); + } if (flagsp != 0) *flagsp = PCI_MAPREG_MEM_CACHEABLE(address) #ifndef __OpenBSD__ diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index e2074e06716..53f6c641a58 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: pcireg.h,v 1.13 2000/08/02 02:25:14 mickey Exp $ */ -/* $NetBSD: pcireg.h,v 1.11 1996/08/10 15:42:33 mycroft Exp $ */ +/* $OpenBSD: pcireg.h,v 1.14 2000/09/20 17:39:05 niklas Exp $ */ +/* $NetBSD: pcireg.h,v 1.26 2000/05/10 16:58:42 thorpej Exp $ */ /* * Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved. @@ -343,6 +343,12 @@ typedef u_int8_t pci_revision_t; (PCI_MAPREG_MEM_ADDR(mr) & -PCI_MAPREG_MEM_ADDR(mr)) #define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0 +#define PCI_MAPREG_MEM64_ADDR(mr) \ + ((mr) & PCI_MAPREG_MEM64_ADDR_MASK) +#define PCI_MAPREG_MEM64_SIZE(mr) \ + (PCI_MAPREG_MEM64_ADDR(mr) & -PCI_MAPREG_MEM64_ADDR(mr)) +#define PCI_MAPREG_MEM64_ADDR_MASK 0xfffffffffffffff0 + #define PCI_MAPREG_IO_ADDR(mr) \ ((mr) & PCI_MAPREG_IO_ADDR_MASK) #define PCI_MAPREG_IO_SIZE(mr) \ |