Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Code to support devices on the DIO and DIO-II bus
0003  * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
0004  * Copyright (C) 2004 Jochen Friedrich <jochen@scram.de>
0005  *
0006  * This code has basically these routines at the moment:
0007  * int dio_find(u_int deviceid)
0008  *    Search the list of DIO devices and return the select code
0009  *    of the next unconfigured device found that matches the given device ID.
0010  *    Note that the deviceid parameter should be the encoded ID.
0011  *    This means that framebuffers should pass it as
0012  *    DIO_ENCODE_ID(DIO_ID_FBUFFER,DIO_ID2_TOPCAT)
0013  *    (or whatever); everybody else just uses DIO_ID_FOOBAR.
0014  * unsigned long dio_scodetophysaddr(int scode)
0015  *    Return the physical address corresponding to the given select code.
0016  * int dio_scodetoipl(int scode)
0017  *    Every DIO card has a fixed interrupt priority level. This function
0018  *    returns it, whatever it is.
0019  * const char *dio_scodetoname(int scode)
0020  *    Return a character string describing this board [might be "" if
0021  *    not CONFIG_DIO_CONSTANTS]
0022  * void dio_config_board(int scode)     mark board as configured in the list
0023  * void dio_unconfig_board(int scode)   mark board as no longer configured
0024  *
0025  * This file is based on the way the Amiga port handles Zorro II cards,
0026  * although we aren't so complicated...
0027  */
0028 #include <linux/module.h>
0029 #include <linux/string.h>
0030 #include <linux/types.h>
0031 #include <linux/kernel.h>
0032 #include <linux/init.h>
0033 #include <linux/dio.h>
0034 #include <linux/slab.h>                         /* kmalloc() */
0035 #include <linux/uaccess.h>
0036 #include <linux/io.h>                           /* readb() */
0037 
0038 struct dio_bus dio_bus = {
0039     .resources = {
0040         /* DIO range */
0041         { .name = "DIO mem", .start = 0x00600000, .end = 0x007fffff },
0042         /* DIO-II range */
0043         { .name = "DIO-II mem", .start = 0x01000000, .end = 0x1fffffff }
0044     },
0045     .name = "DIO bus"
0046 };
0047 
0048 /* not a real config option yet! */
0049 #define CONFIG_DIO_CONSTANTS
0050 
0051 #ifdef CONFIG_DIO_CONSTANTS
0052 /* We associate each numeric ID with an appropriate descriptive string
0053  * using a constant array of these structs.
0054  * FIXME: we should be able to arrange to throw away most of the strings
0055  * using the initdata stuff. Then we wouldn't need to worry about
0056  * carrying them around...
0057  * I think we do this by copying them into newly kmalloc()ed memory and
0058  * marking the names[] array as .initdata ?
0059  */
0060 struct dioname {
0061     int id;
0062     const char *name;
0063 };
0064 
0065 /* useful macro */
0066 #define DIONAME(x) { DIO_ID_##x, DIO_DESC_##x }
0067 #define DIOFBNAME(x) { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_##x), DIO_DESC2_##x }
0068 
0069 static struct dioname names[] = {
0070     DIONAME(DCA0), DIONAME(DCA0REM), DIONAME(DCA1), DIONAME(DCA1REM),
0071     DIONAME(DCM), DIONAME(DCMREM),
0072     DIONAME(LAN),
0073     DIONAME(FHPIB), DIONAME(NHPIB),
0074     DIONAME(SCSI0), DIONAME(SCSI1), DIONAME(SCSI2), DIONAME(SCSI3),
0075     DIONAME(FBUFFER),
0076     DIONAME(PARALLEL), DIONAME(VME), DIONAME(DCL), DIONAME(DCLREM),
0077     DIONAME(MISC0), DIONAME(MISC1), DIONAME(MISC2), DIONAME(MISC3),
0078     DIONAME(MISC4), DIONAME(MISC5), DIONAME(MISC6), DIONAME(MISC7),
0079     DIONAME(MISC8), DIONAME(MISC9), DIONAME(MISC10), DIONAME(MISC11),
0080     DIONAME(MISC12), DIONAME(MISC13),
0081     DIOFBNAME(GATORBOX), DIOFBNAME(TOPCAT), DIOFBNAME(RENAISSANCE),
0082     DIOFBNAME(LRCATSEYE), DIOFBNAME(HRCCATSEYE), DIOFBNAME(HRMCATSEYE),
0083     DIOFBNAME(DAVINCI), DIOFBNAME(XXXCATSEYE), DIOFBNAME(HYPERION),
0084     DIOFBNAME(XGENESIS), DIOFBNAME(TIGER), DIOFBNAME(YGENESIS)
0085 };
0086 
0087 #undef DIONAME
0088 #undef DIOFBNAME
0089 
0090 static const char unknowndioname[]
0091     = "unknown DIO board, please email linux-m68k@lists.linux-m68k.org";
0092 
0093 static const char *dio_getname(int id)
0094 {
0095     /* return pointer to a constant string describing the board with given ID */
0096     unsigned int i;
0097 
0098     for (i = 0; i < ARRAY_SIZE(names); i++)
0099         if (names[i].id == id)
0100             return names[i].name;
0101 
0102     return unknowndioname;
0103 }
0104 
0105 #else
0106 
0107 static char dio_no_name[] = { 0 };
0108 #define dio_getname(_id)    (dio_no_name)
0109 
0110 #endif /* CONFIG_DIO_CONSTANTS */
0111 
0112 int __init dio_find(int deviceid)
0113 {
0114     /* Called to find a DIO device before the full bus scan has run.
0115      * Only used by the console driver.
0116      */
0117     int scode, id;
0118     u_char prid, secid, i;
0119 
0120     for (scode = 0; scode < DIO_SCMAX; scode++) {
0121         void *va;
0122         unsigned long pa;
0123 
0124         if (DIO_SCINHOLE(scode))
0125             continue;
0126 
0127         pa = dio_scodetophysaddr(scode);
0128 
0129         if (!pa)
0130             continue;
0131 
0132         if (scode < DIOII_SCBASE)
0133             va = (void *)(pa + DIO_VIRADDRBASE);
0134         else
0135             va = ioremap(pa, PAGE_SIZE);
0136 
0137         if (copy_from_kernel_nofault(&i,
0138                 (unsigned char *)va + DIO_IDOFF, 1)) {
0139             if (scode >= DIOII_SCBASE)
0140                 iounmap(va);
0141             continue;        /* no board present at that select code */
0142         }
0143 
0144         prid = DIO_ID(va);
0145 
0146         if (DIO_NEEDSSECID(prid)) {
0147             secid = DIO_SECID(va);
0148             id = DIO_ENCODE_ID(prid, secid);
0149         } else
0150             id = prid;
0151 
0152         if (id == deviceid) {
0153             if (scode >= DIOII_SCBASE)
0154                 iounmap(va);
0155             return scode;
0156         }
0157     }
0158 
0159     return -1;
0160 }
0161 
0162 /* This is the function that scans the DIO space and works out what
0163  * hardware is actually present.
0164  */
0165 static int __init dio_init(void)
0166 {
0167     int scode;
0168     int i;
0169     struct dio_dev *dev;
0170     int error;
0171 
0172     if (!MACH_IS_HP300)
0173         return 0;
0174 
0175         printk(KERN_INFO "Scanning for DIO devices...\n");
0176 
0177     /* Initialize the DIO bus */
0178     INIT_LIST_HEAD(&dio_bus.devices);
0179     dev_set_name(&dio_bus.dev, "dio");
0180     error = device_register(&dio_bus.dev);
0181     if (error) {
0182         pr_err("DIO: Error registering dio_bus\n");
0183         return error;
0184     }
0185 
0186     /* Request all resources */
0187     dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2);
0188     for (i = 0; i < dio_bus.num_resources; i++)
0189         request_resource(&iomem_resource, &dio_bus.resources[i]);
0190 
0191     /* Register all devices */
0192     for (scode = 0; scode < DIO_SCMAX; ++scode) {
0193         u_char prid, secid = 0; /* primary, secondary ID bytes */
0194         u_char *va;
0195         unsigned long pa;
0196 
0197         if (DIO_SCINHOLE(scode))
0198             continue;
0199 
0200         pa = dio_scodetophysaddr(scode);
0201 
0202         if (!pa)
0203             continue;
0204 
0205         if (scode < DIOII_SCBASE)
0206             va = (void *)(pa + DIO_VIRADDRBASE);
0207         else
0208             va = ioremap(pa, PAGE_SIZE);
0209 
0210         if (copy_from_kernel_nofault(&i,
0211                 (unsigned char *)va + DIO_IDOFF, 1)) {
0212             if (scode >= DIOII_SCBASE)
0213                 iounmap(va);
0214             continue;         /* no board present at that select code */
0215         }
0216 
0217         /* Found a board, allocate it an entry in the list */
0218         dev = kzalloc(sizeof(struct dio_dev), GFP_KERNEL);
0219         if (!dev) {
0220             if (scode >= DIOII_SCBASE)
0221                 iounmap(va);
0222             return -ENOMEM;
0223         }
0224 
0225         dev->bus = &dio_bus;
0226         dev->dev.parent = &dio_bus.dev;
0227         dev->dev.bus = &dio_bus_type;
0228         dev->scode = scode;
0229         dev->resource.start = pa;
0230         dev->resource.end = pa + DIO_SIZE(scode, va);
0231         dev_set_name(&dev->dev, "%02x", scode);
0232 
0233         /* read the ID byte(s) and encode if necessary. */
0234         prid = DIO_ID(va);
0235 
0236         if (DIO_NEEDSSECID(prid)) {
0237             secid = DIO_SECID(va);
0238             dev->id = DIO_ENCODE_ID(prid, secid);
0239         } else
0240             dev->id = prid;
0241 
0242         dev->ipl = DIO_IPL(va);
0243         strcpy(dev->name, dio_getname(dev->id));
0244                 printk(KERN_INFO "select code %3d: ipl %d: ID %02X", dev->scode, dev->ipl, prid);
0245         if (DIO_NEEDSSECID(prid))
0246                         printk(":%02X", secid);
0247                 printk(": %s\n", dev->name);
0248 
0249         if (scode >= DIOII_SCBASE)
0250             iounmap(va);
0251         error = device_register(&dev->dev);
0252         if (error) {
0253             pr_err("DIO: Error registering device %s\n",
0254                    dev->name);
0255             continue;
0256         }
0257         error = dio_create_sysfs_dev_files(dev);
0258         if (error)
0259             dev_err(&dev->dev, "Error creating sysfs files\n");
0260     }
0261     return 0;
0262 }
0263 
0264 subsys_initcall(dio_init);
0265 
0266 /* Bear in mind that this is called in the very early stages of initialisation
0267  * in order to get the address of the serial port for the console...
0268  */
0269 unsigned long dio_scodetophysaddr(int scode)
0270 {
0271     if (scode >= DIOII_SCBASE)
0272         return (DIOII_BASE + (scode - 132) * DIOII_DEVSIZE);
0273     else if (scode > DIO_SCMAX || scode < 0)
0274         return 0;
0275     else if (DIO_SCINHOLE(scode))
0276         return 0;
0277 
0278     return (DIO_BASE + scode * DIO_DEVSIZE);
0279 }