0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/types.h>
0022 #include <linux/kernel.h>
0023 #include <linux/nubus.h>
0024 #include <linux/proc_fs.h>
0025 #include <linux/seq_file.h>
0026 #include <linux/slab.h>
0027 #include <linux/init.h>
0028 #include <linux/module.h>
0029 #include <linux/uaccess.h>
0030 #include <asm/byteorder.h>
0031
0032
0033
0034
0035
0036 static int
0037 nubus_devices_proc_show(struct seq_file *m, void *v)
0038 {
0039 struct nubus_rsrc *fres;
0040
0041 for_each_func_rsrc(fres)
0042 seq_printf(m, "%x\t%04x %04x %04x %04x\t%08lx\n",
0043 fres->board->slot, fres->category, fres->type,
0044 fres->dr_sw, fres->dr_hw, fres->board->slot_addr);
0045 return 0;
0046 }
0047
0048 static struct proc_dir_entry *proc_bus_nubus_dir;
0049
0050
0051
0052
0053
0054 struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board)
0055 {
0056 char name[2];
0057
0058 if (!proc_bus_nubus_dir)
0059 return NULL;
0060 snprintf(name, sizeof(name), "%x", board->slot);
0061 return proc_mkdir(name, proc_bus_nubus_dir);
0062 }
0063
0064
0065
0066
0067
0068 struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir,
0069 const struct nubus_dirent *ent,
0070 struct nubus_board *board)
0071 {
0072 char name[9];
0073 int lanes = board->lanes;
0074
0075 if (!procdir)
0076 return NULL;
0077 snprintf(name, sizeof(name), "%x", ent->type);
0078 return proc_mkdir_data(name, 0555, procdir, (void *)lanes);
0079 }
0080
0081
0082
0083
0084
0085
0086
0087
0088 struct nubus_proc_pde_data {
0089 unsigned char *res_ptr;
0090 unsigned int res_size;
0091 };
0092
0093 static struct nubus_proc_pde_data *
0094 nubus_proc_alloc_pde_data(unsigned char *ptr, unsigned int size)
0095 {
0096 struct nubus_proc_pde_data *pded;
0097
0098 pded = kmalloc(sizeof(*pded), GFP_KERNEL);
0099 if (!pded)
0100 return NULL;
0101
0102 pded->res_ptr = ptr;
0103 pded->res_size = size;
0104 return pded;
0105 }
0106
0107 static int nubus_proc_rsrc_show(struct seq_file *m, void *v)
0108 {
0109 struct inode *inode = m->private;
0110 struct nubus_proc_pde_data *pded;
0111
0112 pded = pde_data(inode);
0113 if (!pded)
0114 return 0;
0115
0116 if (pded->res_size > m->size)
0117 return -EFBIG;
0118
0119 if (pded->res_size) {
0120 int lanes = (int)proc_get_parent_data(inode);
0121 struct nubus_dirent ent;
0122
0123 if (!lanes)
0124 return 0;
0125
0126 ent.mask = lanes;
0127 ent.base = pded->res_ptr;
0128 ent.data = 0;
0129 nubus_seq_write_rsrc_mem(m, &ent, pded->res_size);
0130 } else {
0131 unsigned int data = (unsigned int)pded->res_ptr;
0132
0133 seq_putc(m, data >> 16);
0134 seq_putc(m, data >> 8);
0135 seq_putc(m, data >> 0);
0136 }
0137 return 0;
0138 }
0139
0140 void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir,
0141 const struct nubus_dirent *ent,
0142 unsigned int size)
0143 {
0144 char name[9];
0145 struct nubus_proc_pde_data *pded;
0146
0147 if (!procdir)
0148 return;
0149
0150 snprintf(name, sizeof(name), "%x", ent->type);
0151 if (size)
0152 pded = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size);
0153 else
0154 pded = NULL;
0155 proc_create_single_data(name, S_IFREG | 0444, procdir,
0156 nubus_proc_rsrc_show, pded);
0157 }
0158
0159 void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
0160 const struct nubus_dirent *ent)
0161 {
0162 char name[9];
0163 unsigned char *data = (unsigned char *)ent->data;
0164
0165 if (!procdir)
0166 return;
0167
0168 snprintf(name, sizeof(name), "%x", ent->type);
0169 proc_create_single_data(name, S_IFREG | 0444, procdir,
0170 nubus_proc_rsrc_show,
0171 nubus_proc_alloc_pde_data(data, 0));
0172 }
0173
0174
0175
0176
0177
0178 void __init nubus_proc_init(void)
0179 {
0180 proc_create_single("nubus", 0, NULL, nubus_proc_show);
0181 proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL);
0182 if (!proc_bus_nubus_dir)
0183 return;
0184 proc_create_single("devices", 0, proc_bus_nubus_dir,
0185 nubus_devices_proc_show);
0186 }