0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
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
0041 { .name = "DIO mem", .start = 0x00600000, .end = 0x007fffff },
0042
0043 { .name = "DIO-II mem", .start = 0x01000000, .end = 0x1fffffff }
0044 },
0045 .name = "DIO bus"
0046 };
0047
0048
0049 #define CONFIG_DIO_CONSTANTS
0050
0051 #ifdef CONFIG_DIO_CONSTANTS
0052
0053
0054
0055
0056
0057
0058
0059
0060 struct dioname {
0061 int id;
0062 const char *name;
0063 };
0064
0065
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
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
0111
0112 int __init dio_find(int deviceid)
0113 {
0114
0115
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;
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
0163
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
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
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
0192 for (scode = 0; scode < DIO_SCMAX; ++scode) {
0193 u_char prid, secid = 0;
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;
0215 }
0216
0217
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
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
0267
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 }