// SPDX-License-Identifier: GPL-2.0 /* Code to support devices on the DIO and DIO-II bus * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk> * Copyright (C) 2004 Jochen Friedrich <jochen@scram.de> * * This code has basically these routines at the moment: * int dio_find(u_int deviceid) * Search the list of DIO devices and return the select code * of the next unconfigured device found that matches the given device ID. * Note that the deviceid parameter should be the encoded ID. * This means that framebuffers should pass it as * DIO_ENCODE_ID(DIO_ID_FBUFFER,DIO_ID2_TOPCAT) * (or whatever); everybody else just uses DIO_ID_FOOBAR. * unsigned long dio_scodetophysaddr(int scode) * Return the physical address corresponding to the given select code. * int dio_scodetoipl(int scode) * Every DIO card has a fixed interrupt priority level. This function * returns it, whatever it is. * const char *dio_scodetoname(int scode) * Return a character string describing this board [might be "" if * not CONFIG_DIO_CONSTANTS] * void dio_config_board(int scode) mark board as configured in the list * void dio_unconfig_board(int scode) mark board as no longer configured * * This file is based on the way the Amiga port handles Zorro II cards, * although we aren't so complicated...
*/ #include <linux/module.h> #include <linux/string.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/dio.h> #include <linux/slab.h> /* kmalloc() */ #include <linux/uaccess.h> #include <linux/io.h> /* readb() */
/* not a real config option yet! */ #define CONFIG_DIO_CONSTANTS
#ifdef CONFIG_DIO_CONSTANTS /* We associate each numeric ID with an appropriate descriptive string * using a constant array of these structs. * FIXME: we should be able to arrange to throw away most of the strings * using the initdata stuff. Then we wouldn't need to worry about * carrying them around... * I think we do this by copying them into newly kmalloc()ed memory and * marking the names[] array as .initdata ?
*/ struct dioname { int id; constchar *name;
};
int __init dio_find(int deviceid)
{ /* Called to find a DIO device before the full bus scan has run. * Only used by the console driver.
*/ int scode, id;
u_char prid, secid, i;
if (scode < DIOII_SCBASE)
va = (void *)(pa + DIO_VIRADDRBASE); else
va = ioremap(pa, PAGE_SIZE);
if (copy_from_kernel_nofault(&i,
(unsignedchar *)va + DIO_IDOFF, 1)) { if (scode >= DIOII_SCBASE)
iounmap(va); continue; /* no board present at that select code */
}
prid = DIO_ID(va);
if (DIO_NEEDSSECID(prid)) {
secid = DIO_SECID(va);
id = DIO_ENCODE_ID(prid, secid);
} else
id = prid;
if (id == deviceid) { if (scode >= DIOII_SCBASE)
iounmap(va); return scode;
}
}
return -1;
}
/* This is the function that scans the DIO space and works out what * hardware is actually present.
*/ staticint __init dio_init(void)
{ int scode; int i; struct dio_dev *dev; int error;
if (!MACH_IS_HP300) return 0;
printk(KERN_INFO "Scanning for DIO devices...\n");
/* Initialize the DIO bus */
INIT_LIST_HEAD(&dio_bus.devices);
dev_set_name(&dio_bus.dev, "dio");
error = device_register(&dio_bus.dev); if (error) {
pr_err("DIO: Error registering dio_bus\n"); return error;
}
/* Request all resources */
dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2); for (i = 0; i < dio_bus.num_resources; i++)
request_resource(&iomem_resource, &dio_bus.resources[i]);
/* Register all devices */ for (scode = 0; scode < DIO_SCMAX; ++scode) {
u_char prid, secid = 0; /* primary, secondary ID bytes */
u_char *va; unsignedlong pa;
if (DIO_SCINHOLE(scode)) continue;
pa = dio_scodetophysaddr(scode);
if (!pa) continue;
if (scode < DIOII_SCBASE)
va = (void *)(pa + DIO_VIRADDRBASE); else
va = ioremap(pa, PAGE_SIZE);
if (copy_from_kernel_nofault(&i,
(unsignedchar *)va + DIO_IDOFF, 1)) { if (scode >= DIOII_SCBASE)
iounmap(va); continue; /* no board present at that select code */
}
/* Found a board, allocate it an entry in the list */
dev = kzalloc(sizeof(struct dio_dev), GFP_KERNEL); if (!dev) { if (scode >= DIOII_SCBASE)
iounmap(va); return -ENOMEM;
}
/* Bear in mind that this is called in the very early stages of initialisation * in order to get the address of the serial port for the console...
*/ unsignedlong dio_scodetophysaddr(int scode)
{ if (scode >= DIOII_SCBASE) return (DIOII_BASE + (scode - 132) * DIOII_DEVSIZE); elseif (scode > DIO_SCMAX || scode < 0) return 0; elseif (DIO_SCINHOLE(scode)) return 0;
return (DIO_BASE + scode * DIO_DEVSIZE);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.