mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
parisc architecture fixes and updates for kernel v7.4-rc1:
- fix out-of-bounds read in eisa_enumerator driver - drop redundant pte_xxx() macros and use common macros - code cleanup in eisa_enumerator driver - typo fixes in comments in various header files -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCat5hYQAKCRD3ErUQojoP X1kUAQDhYXNh06+H6EvTsQmbYWPhTW/4XAnVoFV8J00IWnLhtgD+JT4d6QsM6Pt0 n6Qoujjyc+Z6lq0wz3ikk5CCwv4RMQk= =II3T -----END PGP SIGNATURE----- Merge tag 'parisc-for-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux Pull parisc updates from Helge Deller: - fix out-of-bounds read in eisa_enumerator driver - drop redundant pte_xxx() macros and use common macros - code cleanup in eisa_enumerator driver - typo fixes in comments in various header files * tag 'parisc-for-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: parisc: eisa_enumerator: Code and whitespace cleanups parisc: eisa_enumerator: Fix out-of-bounds reads of the EEPROM buffer parisc: Drop redundant implementation of ptep_set_wrprotect() parisc: Drop redundant implementation of pte_same() parisc: Drop own implementations for ptep_get() and ptep_test_and_clear_young() parisc: fix typos in comments in parport.c parisc: fix typos in comments in sba_iommu.c parisc: fix typos in comments in pdc_stable.c parisc: fix typos in comments in dino.c parisc: fix typos in comments in ccio-dma.c parisc: fix typos in comments in memcpy.c parisc: fix typos in comments in mman.h parisc: fix typos in comments in special_insns.h parisc: fix typos in comments in pdcpat.h
This commit is contained in:
commit
6b4b543fa1
|
|
@ -54,7 +54,7 @@
|
|||
#define PAT_GMMIO 2 /* > 4G MMIO Space */
|
||||
#define PAT_NPIOP 3 /* Non Postable I/O Port Space */
|
||||
#define PAT_PIOP 4 /* Postable I/O Port Space */
|
||||
#define PAT_AHPA 5 /* Addional HPA Space */
|
||||
#define PAT_AHPA 5 /* Additional HPA Space */
|
||||
#define PAT_UFO 6 /* HPA Space (UFO for Mariposa) */
|
||||
#define PAT_GNIP 7 /* GNI Reserved Space */
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ struct pdc_pat_pd_addr_map_entry {
|
|||
* ----------------------------------------------------------
|
||||
* Bit 0 to 51 - conf_base_addr
|
||||
* Bit 52 to 62 - reserved
|
||||
* Bit 63 - endianess bit
|
||||
* Bit 63 - endianness bit
|
||||
********************************************************************/
|
||||
#define PAT_GET_CBA(value) ((value) & 0xfffffffffffff000UL)
|
||||
|
||||
|
|
|
|||
|
|
@ -423,36 +423,9 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
|
|||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t ptep_get(pte_t *ptep)
|
||||
{
|
||||
return READ_ONCE(*ptep);
|
||||
}
|
||||
#define ptep_get ptep_get
|
||||
|
||||
static inline bool ptep_test_and_clear_young(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t pte;
|
||||
|
||||
pte = ptep_get(ptep);
|
||||
if (!pte_young(pte)) {
|
||||
return false;
|
||||
}
|
||||
set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ptep_clear_flush_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep);
|
||||
pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep);
|
||||
|
||||
struct mm_struct;
|
||||
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
set_pte_at(mm, addr, ptep, pte_wrprotect(*ptep));
|
||||
}
|
||||
|
||||
#define pte_same(A,B) (pte_val(A) == pte_val(B))
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
|
||||
|
|
@ -482,10 +455,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
|
|||
#define HAVE_ARCH_UNMAPPED_AREA
|
||||
#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
|
||||
|
||||
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
|
||||
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
|
||||
#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
|
||||
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
|
||||
#define __HAVE_ARCH_PTE_SAME
|
||||
|
||||
#endif /* _PARISC_PGTABLE_H */
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
/**
|
||||
* prober_user() - Probe user read access
|
||||
* @sr: Space regster.
|
||||
* @sr: Space register.
|
||||
* @va: Virtual address.
|
||||
*
|
||||
* Return: Non-zero if address is accessible.
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
#define MADV_HUGEPAGE 14 /* Worth backing with hugepages */
|
||||
#define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages */
|
||||
|
||||
#define MADV_DONTDUMP 16 /* Explicity exclude from the core dump,
|
||||
#define MADV_DONTDUMP 16 /* Explicitly exclude from the core dump,
|
||||
overrides the coredump filter bits */
|
||||
#define MADV_DODUMP 17 /* Clear the MADV_NODUMP flag */
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ unsigned long raw_copy_from_user(void *dst, const void __user *src,
|
|||
break;
|
||||
}
|
||||
start += PAGE_SIZE;
|
||||
/* align to page boundry which may have different permission */
|
||||
/* align to page boundary which may have different permission */
|
||||
start = PAGE_ALIGN_DOWN(start);
|
||||
}
|
||||
return len - newlen + pa_memcpy(dst, (void __force *)src, newlen);
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
|
|||
* @pages_mapped: The requested number of pages to be freed from the
|
||||
* I/O Pdir.
|
||||
*
|
||||
* This function frees the resouces allocated for the iova.
|
||||
* This function frees the resources allocated for the iova.
|
||||
*/
|
||||
static void
|
||||
ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped)
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ dino_card_fixup(struct pci_dev *dev)
|
|||
dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq);
|
||||
}
|
||||
|
||||
/* The alignment contraints for PCI bridges under dino */
|
||||
/* The alignment constraints for PCI bridges under dino */
|
||||
#define DINO_BRIDGE_ALIGN 0x100000
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,341 +6,299 @@
|
|||
*/
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include <asm/eisa_bus.h>
|
||||
#include <asm/eisa_eeprom.h>
|
||||
|
||||
|
||||
/*
|
||||
* Todo:
|
||||
*
|
||||
* PORT init with MASK attr and other size than byte
|
||||
* MEMORY with other decode than 20 bit
|
||||
* CRC stuff
|
||||
* FREEFORM stuff
|
||||
* TODO:
|
||||
* - PORT init with MASK attr and other size than byte
|
||||
* - MEMORY with other decode than 20 bit
|
||||
* - CRC stuff
|
||||
* - FREEFORM stuff
|
||||
*/
|
||||
|
||||
#define EPI 0xc80
|
||||
#define NUM_SLOT 16
|
||||
#define SLOT2PORT(x) (x<<12)
|
||||
#define SLOT2PORT(x) (x << 12)
|
||||
|
||||
|
||||
/* macros to handle unaligned accesses and
|
||||
* byte swapping. The data in the EEPROM is
|
||||
* little-endian on the big-endian PAROSC */
|
||||
#define get_8(x) (*(u_int8_t*)(x))
|
||||
|
||||
static inline u_int16_t get_16(const unsigned char *x)
|
||||
{
|
||||
return (x[1] << 8) | x[0];
|
||||
}
|
||||
|
||||
static inline u_int32_t get_32(const unsigned char *x)
|
||||
{
|
||||
return (x[3] << 24) | (x[2] << 16) | (x[1] << 8) | x[0];
|
||||
}
|
||||
|
||||
static inline u_int32_t get_24(const unsigned char *x)
|
||||
{
|
||||
return (x[2] << 24) | (x[1] << 16) | (x[0] << 8);
|
||||
}
|
||||
/* EEPROM data is little-endian, PA-RISC is big-endian. */
|
||||
#define get_8(x) (*(u_int8_t *)(x))
|
||||
#define get_16(x) get_unaligned_le16(x)
|
||||
#define get_32(x) get_unaligned_le32(x)
|
||||
#define get_24(x) (get_unaligned_le32(x) & 0x00ffffff)
|
||||
|
||||
static void print_eisa_id(char *s, u_int32_t id)
|
||||
{
|
||||
char vendor[4];
|
||||
int rev;
|
||||
int device;
|
||||
|
||||
|
||||
rev = id & 0xff;
|
||||
id >>= 8;
|
||||
device = id & 0xff;
|
||||
id >>= 8;
|
||||
vendor[3] = '\0';
|
||||
vendor[2] = '@' + (id & 0x1f);
|
||||
id >>= 5;
|
||||
id >>= 5;
|
||||
vendor[1] = '@' + (id & 0x1f);
|
||||
id >>= 5;
|
||||
id >>= 5;
|
||||
vendor[0] = '@' + (id & 0x1f);
|
||||
id >>= 5;
|
||||
|
||||
id >>= 5;
|
||||
|
||||
sprintf(s, "%s%02X%02X", vendor, device, rev);
|
||||
}
|
||||
|
||||
static int configure_memory(const unsigned char *buf,
|
||||
|
||||
static int configure_memory(const unsigned char *buf,
|
||||
struct resource *mem_parent,
|
||||
char *name)
|
||||
{
|
||||
int len;
|
||||
u_int8_t c;
|
||||
int i;
|
||||
struct resource *res;
|
||||
|
||||
len=0;
|
||||
|
||||
for (i=0;i<HPEE_MEMORY_MAX_ENT;i++) {
|
||||
c = get_8(buf+len);
|
||||
|
||||
int i, len = 0;
|
||||
|
||||
for (i = 0; i < HPEE_MEMORY_MAX_ENT; i++) {
|
||||
struct resource *res;
|
||||
u_int8_t c = get_8(buf + len);
|
||||
|
||||
if (NULL != (res = kzalloc_obj(struct resource))) {
|
||||
int result;
|
||||
|
||||
|
||||
res->name = name;
|
||||
res->start = mem_parent->start + get_24(buf+len+2);
|
||||
res->end = res->start + get_16(buf+len+5)*1024;
|
||||
res->start = mem_parent->start + get_24(buf + len + 2);
|
||||
res->end = res->start + get_16(buf + len + 5) * 1024;
|
||||
res->flags = IORESOURCE_MEM;
|
||||
pr_cont("memory %pR ", res);
|
||||
result = request_resource(mem_parent, res);
|
||||
if (result < 0) {
|
||||
printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
|
||||
pr_err("EISA Enumerator: failed to claim EISA Bus address space!\n");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
len+=7;
|
||||
|
||||
if (!(c & HPEE_MEMORY_MORE)) {
|
||||
|
||||
len += 7;
|
||||
|
||||
if (!(c & HPEE_MEMORY_MORE))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int configure_irq(const unsigned char *buf)
|
||||
{
|
||||
int len;
|
||||
u_int8_t c;
|
||||
int i;
|
||||
|
||||
len=0;
|
||||
|
||||
for (i=0;i<HPEE_IRQ_MAX_ENT;i++) {
|
||||
c = get_8(buf+len);
|
||||
|
||||
int i, len = 0;
|
||||
|
||||
for (i = 0; i < HPEE_IRQ_MAX_ENT; i++) {
|
||||
u_int8_t c = get_8(buf + len);
|
||||
|
||||
pr_cont("IRQ %d ", c & HPEE_IRQ_CHANNEL_MASK);
|
||||
if (c & HPEE_IRQ_TRIG_LEVEL) {
|
||||
eisa_make_irq_level(c & HPEE_IRQ_CHANNEL_MASK);
|
||||
} else {
|
||||
eisa_make_irq_edge(c & HPEE_IRQ_CHANNEL_MASK);
|
||||
}
|
||||
|
||||
len+=2;
|
||||
/* hpux seems to allow for
|
||||
* two bytes of irq data but only defines one of
|
||||
* them, I think */
|
||||
if (!(c & HPEE_IRQ_MORE)) {
|
||||
|
||||
len += 2;
|
||||
/*
|
||||
* HP-UX seems to allow for two bytes of irq data but
|
||||
* only defines one of them, I think
|
||||
*/
|
||||
if (!(c & HPEE_IRQ_MORE))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int configure_dma(const unsigned char *buf)
|
||||
{
|
||||
int len;
|
||||
u_int8_t c;
|
||||
int i;
|
||||
|
||||
len=0;
|
||||
|
||||
for (i=0;i<HPEE_DMA_MAX_ENT;i++) {
|
||||
c = get_8(buf+len);
|
||||
int i, len = 0;
|
||||
|
||||
for (i = 0; i < HPEE_DMA_MAX_ENT; i++) {
|
||||
u_int8_t c = get_8(buf + len);
|
||||
pr_cont("DMA %d ", c&HPEE_DMA_CHANNEL_MASK);
|
||||
/* fixme: maybe initialize the dma channel withthe timing ? */
|
||||
len+=2;
|
||||
if (!(c & HPEE_DMA_MORE)) {
|
||||
len += 2;
|
||||
if (!(c & HPEE_DMA_MORE))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int configure_port(const unsigned char *buf, struct resource *io_parent,
|
||||
char *board)
|
||||
{
|
||||
int len;
|
||||
u_int8_t c;
|
||||
int i;
|
||||
struct resource *res;
|
||||
int result;
|
||||
|
||||
len=0;
|
||||
|
||||
for (i=0;i<HPEE_PORT_MAX_ENT;i++) {
|
||||
c = get_8(buf+len);
|
||||
|
||||
int i, result, len = 0;
|
||||
|
||||
for (i = 0; i < HPEE_PORT_MAX_ENT; i++) {
|
||||
struct resource *res;
|
||||
u_int8_t c = get_8(buf + len);
|
||||
|
||||
if (NULL != (res = kzalloc_obj(struct resource))) {
|
||||
res->name = board;
|
||||
res->start = get_16(buf+len+1);
|
||||
res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1;
|
||||
res->start = get_16(buf + len + 1);
|
||||
res->end = res->start + (c & HPEE_PORT_SIZE_MASK) + 1;
|
||||
res->flags = IORESOURCE_IO;
|
||||
pr_cont("ioports %pR ", res);
|
||||
result = request_resource(io_parent, res);
|
||||
if (result < 0) {
|
||||
printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
|
||||
pr_err("EISA Enumerator: failed to claim EISA Bus address space!\n");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
len+=3;
|
||||
if (!(c & HPEE_PORT_MORE)) {
|
||||
len += 3;
|
||||
if (!(c & HPEE_PORT_MORE))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/* byte 1 and 2 is the port number to write
|
||||
* and at byte 3 the value to write starts.
|
||||
* I assume that there are and- and or- masks
|
||||
* here when HPEE_PORT_INIT_MASK is set but I have
|
||||
* not yet encountered this. */
|
||||
/*
|
||||
* Byte 1 and 2 is the port number to write and at byte 3 the value to write
|
||||
* starts. I assume that there are and- and or- masks here when
|
||||
* HPEE_PORT_INIT_MASK is set but I have not yet encountered this.
|
||||
*/
|
||||
static int configure_port_init(const unsigned char *buf)
|
||||
{
|
||||
int len=0;
|
||||
u_int8_t c;
|
||||
|
||||
while (len<HPEE_PORT_INIT_MAX_LEN) {
|
||||
int s=0;
|
||||
c = get_8(buf+len);
|
||||
|
||||
switch (c & HPEE_PORT_INIT_WIDTH_MASK) {
|
||||
int len = 0;
|
||||
|
||||
while (len < HPEE_PORT_INIT_MAX_LEN) {
|
||||
int s = 0;
|
||||
u_int8_t c = get_8(buf + len);
|
||||
|
||||
switch (c & HPEE_PORT_INIT_WIDTH_MASK) {
|
||||
case HPEE_PORT_INIT_WIDTH_BYTE:
|
||||
s=1;
|
||||
s = 1;
|
||||
if (c & HPEE_PORT_INIT_MASK) {
|
||||
printk(KERN_WARNING "port_init: unverified mask attribute\n");
|
||||
outb((inb(get_16(buf+len+1) &
|
||||
get_8(buf+len+3)) |
|
||||
get_8(buf+len+4)), get_16(buf+len+1));
|
||||
|
||||
pr_warn("port_init: unverified mask attribute\n");
|
||||
outb((inb(get_16(buf + len + 1) &
|
||||
get_8(buf + len + 3)) |
|
||||
get_8(buf + len + 4)),
|
||||
get_16(buf + len + 1));
|
||||
} else {
|
||||
outb(get_8(buf+len+3), get_16(buf+len+1));
|
||||
|
||||
outb(get_8(buf + len + 3),
|
||||
get_16(buf + len + 1));
|
||||
}
|
||||
break;
|
||||
case HPEE_PORT_INIT_WIDTH_WORD:
|
||||
s=2;
|
||||
s = 2;
|
||||
if (c & HPEE_PORT_INIT_MASK) {
|
||||
printk(KERN_WARNING "port_init: unverified mask attribute\n");
|
||||
outw((inw(get_16(buf+len+1)) &
|
||||
get_16(buf+len+3)) |
|
||||
get_16(buf+len+5),
|
||||
get_16(buf+len+1));
|
||||
pr_warn("port_init: unverified mask attribute\n");
|
||||
outw((inw(get_16(buf + len + 1)) &
|
||||
get_16(buf + len + 3)) |
|
||||
get_16(buf + len + 5),
|
||||
get_16(buf + len + 1));
|
||||
} else {
|
||||
outw(cpu_to_le16(get_16(buf+len+3)), get_16(buf+len+1));
|
||||
outw(cpu_to_le16(get_16(buf + len + 3)),
|
||||
get_16(buf + len + 1));
|
||||
}
|
||||
break;
|
||||
case HPEE_PORT_INIT_WIDTH_DWORD:
|
||||
s=4;
|
||||
s = 4;
|
||||
if (c & HPEE_PORT_INIT_MASK) {
|
||||
printk(KERN_WARNING "port_init: unverified mask attribute\n");
|
||||
outl((inl(get_16(buf+len+1) &
|
||||
get_32(buf+len+3)) |
|
||||
get_32(buf+len+7)), get_16(buf+len+1));
|
||||
pr_warn("port_init: unverified mask attribute\n");
|
||||
outl((inl(get_16(buf + len + 1) &
|
||||
get_32(buf + len + 3)) |
|
||||
get_32(buf + len + 7)), get_16(buf + len + 1));
|
||||
} else {
|
||||
outl(cpu_to_le32(get_32(buf+len+3)), get_16(buf+len+1));
|
||||
outl(cpu_to_le32(get_32(buf + len + 3)),
|
||||
get_16(buf + len + 1));
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "Invalid port init word %02x\n", c);
|
||||
pr_warn("Invalid port init word %02x\n", c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c & HPEE_PORT_INIT_MASK) {
|
||||
s*=2;
|
||||
}
|
||||
|
||||
len+=s+3;
|
||||
if (!(c & HPEE_PORT_INIT_MORE)) {
|
||||
|
||||
if (c & HPEE_PORT_INIT_MASK)
|
||||
s *= 2;
|
||||
|
||||
len += s + 3;
|
||||
if (!(c & HPEE_PORT_INIT_MORE))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int configure_choise(const unsigned char *buf, u_int8_t *info)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* theis record contain the value of the functions
|
||||
* configuration choises and an info byte which
|
||||
* describes which other records to expect in this
|
||||
* function */
|
||||
|
||||
/*
|
||||
* This record contain the value of the functions configuration
|
||||
* chooses and an info byte which describes which other records to
|
||||
* expect in this function.
|
||||
*/
|
||||
len = get_8(buf);
|
||||
*info=get_8(buf+len+1);
|
||||
|
||||
return len+2;
|
||||
*info = get_8(buf + len + 1);
|
||||
|
||||
return len + 2;
|
||||
}
|
||||
|
||||
static int configure_type_string(const unsigned char *buf)
|
||||
static int configure_type_string(const unsigned char *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
|
||||
/* just skip past the type field */
|
||||
len = get_8(buf);
|
||||
if (len > 80) {
|
||||
printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len);
|
||||
pr_err("eisa_enumerator: type info field too long (%d, max is 80)\n", len);
|
||||
}
|
||||
|
||||
return 1+len;
|
||||
|
||||
return 1 + len;
|
||||
}
|
||||
|
||||
static int configure_function(const unsigned char *buf, int *more)
|
||||
static int configure_function(const unsigned char *buf, int *more)
|
||||
{
|
||||
/* the init field seems to be a two-byte field
|
||||
* which is non-zero if there are an other function following
|
||||
* I think it is the length of the function def
|
||||
* I think it is the length of the function def
|
||||
*/
|
||||
*more = get_16(buf);
|
||||
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int parse_slot_config(int slot,
|
||||
const unsigned char *buf,
|
||||
struct eeprom_eisa_slot_info *es,
|
||||
unsigned int buflen,
|
||||
struct eeprom_eisa_slot_info *es,
|
||||
struct resource *io_parent,
|
||||
struct resource *mem_parent)
|
||||
{
|
||||
int res=0;
|
||||
int res = 0;
|
||||
int function_len;
|
||||
unsigned int pos=0;
|
||||
unsigned int pos = 0;
|
||||
unsigned int maxlen;
|
||||
int num_func=0;
|
||||
int num_func = 0;
|
||||
u_int8_t flags;
|
||||
int p0;
|
||||
|
||||
|
||||
char *board;
|
||||
int id_string_used=0;
|
||||
|
||||
int id_string_used = 0;
|
||||
|
||||
if (NULL == (board = kmalloc(8, GFP_KERNEL))) {
|
||||
return -1;
|
||||
}
|
||||
print_eisa_id(board, es->eisa_slot_id);
|
||||
printk(KERN_INFO "EISA slot %d: %s %s ",
|
||||
pr_info("EISA slot %d: %s %s ",
|
||||
slot, board, es->flags&HPEE_FLAG_BOARD_IS_ISA ? "ISA" : "EISA");
|
||||
|
||||
maxlen = es->config_data_length < HPEE_MAX_LENGTH ?
|
||||
es->config_data_length : HPEE_MAX_LENGTH;
|
||||
|
||||
/* never parse beyond the data that is actually in the buffer */
|
||||
maxlen = min_t(unsigned int, es->config_data_length, buflen);
|
||||
while ((pos < maxlen) && (num_func <= es->num_functions)) {
|
||||
pos+=configure_function(buf+pos, &function_len);
|
||||
|
||||
if (!function_len) {
|
||||
pos += configure_function(buf + pos, &function_len);
|
||||
|
||||
if (!function_len)
|
||||
break;
|
||||
}
|
||||
|
||||
num_func++;
|
||||
p0 = pos;
|
||||
pos += configure_choise(buf+pos, &flags);
|
||||
|
|
@ -352,51 +310,49 @@ static int parse_slot_config(int slot,
|
|||
}
|
||||
if (flags & HPEE_FUNCTION_INFO_CFG_FREE_FORM) {
|
||||
/* I have no idea how to handle this */
|
||||
printk("function %d have free-form configuration, skipping ",
|
||||
pr_err("function %d have free-form configuration, skipping ",
|
||||
num_func);
|
||||
pos = p0 + function_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* the ordering of the sections need
|
||||
* more investigation.
|
||||
* Currently I think that memory comaed before IRQ
|
||||
* I assume the order is LSB to MSB in the
|
||||
* info flags
|
||||
* eg type, memory, irq, dma, port, HPEE_PORT_init
|
||||
/* the ordering of the sections need more investigation.
|
||||
* Currently I think that memory command before IRQ
|
||||
* I assume the order is LSB to MSB in the info flags
|
||||
* eg type, memory, irq, dma, port, HPEE_PORT_init
|
||||
*/
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_TYPE) {
|
||||
pos += configure_type_string(buf+pos);
|
||||
pos += configure_type_string(buf + pos);
|
||||
}
|
||||
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_MEMORY) {
|
||||
id_string_used=1;
|
||||
pos += configure_memory(buf+pos, mem_parent, board);
|
||||
}
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_IRQ) {
|
||||
pos += configure_irq(buf+pos);
|
||||
}
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_DMA) {
|
||||
pos += configure_dma(buf+pos);
|
||||
}
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_PORT) {
|
||||
id_string_used=1;
|
||||
pos += configure_port(buf+pos, io_parent, board);
|
||||
}
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_PORT_INIT) {
|
||||
pos += configure_port_init(buf+pos);
|
||||
id_string_used = 1;
|
||||
pos += configure_memory(buf + pos, mem_parent, board);
|
||||
}
|
||||
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_IRQ) {
|
||||
pos += configure_irq(buf + pos);
|
||||
}
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_DMA) {
|
||||
pos += configure_dma(buf + pos);
|
||||
}
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_PORT) {
|
||||
id_string_used = 1;
|
||||
pos += configure_port(buf + pos, io_parent, board);
|
||||
}
|
||||
|
||||
if (flags & HPEE_FUNCTION_INFO_HAVE_PORT_INIT) {
|
||||
pos += configure_port_init(buf + pos);
|
||||
}
|
||||
|
||||
if (p0 + function_len < pos) {
|
||||
printk(KERN_ERR "eisa_enumerator: function %d length mismatch "
|
||||
pr_err("eisa_enumerator: function %d length mismatch "
|
||||
"got %d, expected %d\n",
|
||||
num_func, pos-p0, function_len);
|
||||
res=-1;
|
||||
num_func, pos - p0, function_len);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
pos = p0 + function_len;
|
||||
|
|
@ -405,112 +361,107 @@ static int parse_slot_config(int slot,
|
|||
if (!id_string_used) {
|
||||
kfree(board);
|
||||
}
|
||||
|
||||
|
||||
if (pos != es->config_data_length) {
|
||||
printk(KERN_ERR "eisa_enumerator: config data length mismatch got %d, expected %d\n",
|
||||
pr_err("eisa_enumerator: config data length mismatch got %d, expected %d\n",
|
||||
pos, es->config_data_length);
|
||||
res=-1;
|
||||
res = -1;
|
||||
}
|
||||
|
||||
|
||||
if (num_func != es->num_functions) {
|
||||
printk(KERN_ERR "eisa_enumerator: number of functions mismatch got %d, expected %d\n",
|
||||
pr_err("eisa_enumerator: number of functions mismatch got %d, expected %d\n",
|
||||
num_func, es->num_functions);
|
||||
res=-2;
|
||||
res = -2;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
static int init_slot(int slot, struct eeprom_eisa_slot_info *es)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
char id_string[8];
|
||||
|
||||
if (!(es->slot_info&HPEE_SLOT_INFO_NO_READID)) {
|
||||
char id_string[8], id_string2[8];
|
||||
|
||||
if (!(es->slot_info & HPEE_SLOT_INFO_NO_READID)) {
|
||||
/* try to read the id of the board in the slot */
|
||||
id = le32_to_cpu(inl(SLOT2PORT(slot)+EPI));
|
||||
|
||||
id = le32_to_cpu(inl(SLOT2PORT(slot) + EPI));
|
||||
|
||||
if (0xffffffff == id) {
|
||||
/* Maybe we didn't expect a card to be here... */
|
||||
if (es->eisa_slot_id == 0xffffffff)
|
||||
return -1;
|
||||
|
||||
/* this board is not here or it does not
|
||||
* support readid
|
||||
*/
|
||||
printk(KERN_ERR "EISA slot %d a configured board was not detected (",
|
||||
slot);
|
||||
|
||||
|
||||
/* board is not here or it does not support readid */
|
||||
print_eisa_id(id_string, es->eisa_slot_id);
|
||||
printk(" expected %s)\n", id_string);
|
||||
|
||||
return -1;
|
||||
pr_err("EISA slot %d a configured board was not detected (expected %s)\n",
|
||||
slot, id_string);
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (es->eisa_slot_id != id) {
|
||||
print_eisa_id(id_string, id);
|
||||
printk(KERN_ERR "EISA slot %d id mismatch: got %s",
|
||||
slot, id_string);
|
||||
|
||||
print_eisa_id(id_string, es->eisa_slot_id);
|
||||
printk(" expected %s\n", id_string);
|
||||
|
||||
return -1;
|
||||
|
||||
print_eisa_id(id_string2, es->eisa_slot_id);
|
||||
pr_err("EISA slot %d id mismatch: got %s expected %s\n",
|
||||
slot, id_string, id_string2);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* now: we need to enable the board if
|
||||
|
||||
/* now: we need to enable the board if
|
||||
* it supports enabling and run through
|
||||
* the port init sction if present
|
||||
* and finally record any interrupt polarity
|
||||
*/
|
||||
if (es->slot_features & HPEE_SLOT_FEATURES_ENABLE) {
|
||||
/* enable board */
|
||||
outb(0x01| inb(SLOT2PORT(slot)+EPI+4),
|
||||
SLOT2PORT(slot)+EPI+4);
|
||||
outb(0x01 | inb(SLOT2PORT(slot) + EPI + 4),
|
||||
SLOT2PORT(slot) + EPI + 4);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int eisa_enumerator(unsigned long eeprom_addr,
|
||||
struct resource *io_parent, struct resource *mem_parent)
|
||||
struct resource *io_parent, struct resource *mem_parent)
|
||||
{
|
||||
int i;
|
||||
struct eeprom_header *eh;
|
||||
static char eeprom_buf[HPEE_MAX_LENGTH];
|
||||
|
||||
for (i=0; i < HPEE_MAX_LENGTH; i++) {
|
||||
eeprom_buf[i] = gsc_readb(eeprom_addr+i);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Enumerating EISA bus\n");
|
||||
|
||||
|
||||
for (i = 0; i < HPEE_MAX_LENGTH; i++)
|
||||
eeprom_buf[i] = gsc_readb(eeprom_addr + i);
|
||||
|
||||
pr_info("Enumerating EISA bus\n");
|
||||
|
||||
eh = (struct eeprom_header*)(eeprom_buf);
|
||||
for (i=0;i<eh->num_slots;i++) {
|
||||
/*
|
||||
* The EEPROM contents are not to be trusted: clamp the number of
|
||||
* slots so that all slot records fit into eeprom_buf.
|
||||
*/
|
||||
eh->num_slots = min_t(u8, eh->num_slots,
|
||||
(HPEE_MAX_LENGTH - sizeof(*eh)) /
|
||||
sizeof(struct eeprom_eisa_slot_info));
|
||||
for (i = 0; i < eh->num_slots; i++) {
|
||||
struct eeprom_eisa_slot_info *es;
|
||||
|
||||
|
||||
es = (struct eeprom_eisa_slot_info*)
|
||||
(&eeprom_buf[HPEE_SLOT_INFO(i)]);
|
||||
|
||||
if (-1==init_slot(i+1, es)) {
|
||||
|
||||
if (-1 == init_slot(i + 1, es))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (es->config_data_offset < HPEE_MAX_LENGTH) {
|
||||
if (parse_slot_config(i+1, &eeprom_buf[es->config_data_offset],
|
||||
es, io_parent, mem_parent)) {
|
||||
if (parse_slot_config(i + 1, &eeprom_buf[es->config_data_offset],
|
||||
HPEE_MAX_LENGTH - es->config_data_offset,
|
||||
es, io_parent, mem_parent)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
printk (KERN_WARNING "EISA EEPROM offset 0x%x out of range\n",es->config_data_offset);
|
||||
pr_err("EISA EEPROM offset 0x%x out of range\n",
|
||||
es->config_data_offset);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return eh->num_slots;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -586,7 +586,7 @@ static ssize_t pdcs_autosearch_read(struct kobject *kobj,
|
|||
* @attr: The kobject attributes.
|
||||
* @buf: The output buffer to write to.
|
||||
*
|
||||
* The value of the timer field correponds to a number of seconds in powers of 2.
|
||||
* The value of the timer field corresponds to a number of seconds in powers of 2.
|
||||
*/
|
||||
static ssize_t pdcs_timer_read(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
|
|
|
|||
|
|
@ -599,7 +599,7 @@ sba_io_pdir_entry(__le64 *pdir_ptr, space_t sid, phys_addr_t pba,
|
|||
* corresponding IO TLB entry. The Ike PCOM (Purge Command Register)
|
||||
* is to purge stale entries in the IO TLB when unmapping entries.
|
||||
*
|
||||
* The PCOM register supports purging of multiple pages, with a minium
|
||||
* The PCOM register supports purging of multiple pages, with a minimum
|
||||
* of 1 page and a maximum of 2GB. Hardware requires the address be
|
||||
* aligned to the size of the range being purged. The size of the range
|
||||
* must be a power of 2. The "Cool perf optimization" in the
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ static int __init parport_init_chip(struct parisc_device *dev)
|
|||
*/
|
||||
if (boot_cpu_data.cpu_type > pcxt && !pdc_add_valid(port+4)) {
|
||||
|
||||
/* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */
|
||||
/* Initialize bidirectional-mode (0x10) & data-transfer-mode #1 (0x20) */
|
||||
pr_info("%s: initialize bidirectional-mode\n", __func__);
|
||||
parport_writeb ( (0x10 + 0x20), port + 4);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user