0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/rio.h>
0011 #include <linux/rio_drv.h>
0012 #include <linux/stat.h>
0013 #include <linux/capability.h>
0014
0015 #include "rio.h"
0016
0017
0018 #define rio_config_attr(field, format_string) \
0019 static ssize_t \
0020 field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
0021 { \
0022 struct rio_dev *rdev = to_rio_dev(dev); \
0023 \
0024 return sprintf(buf, format_string, rdev->field); \
0025 } \
0026 static DEVICE_ATTR_RO(field);
0027
0028 rio_config_attr(did, "0x%04x\n");
0029 rio_config_attr(vid, "0x%04x\n");
0030 rio_config_attr(device_rev, "0x%08x\n");
0031 rio_config_attr(asm_did, "0x%04x\n");
0032 rio_config_attr(asm_vid, "0x%04x\n");
0033 rio_config_attr(asm_rev, "0x%04x\n");
0034 rio_config_attr(destid, "0x%04x\n");
0035 rio_config_attr(hopcount, "0x%02x\n");
0036
0037 static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf)
0038 {
0039 struct rio_dev *rdev = to_rio_dev(dev);
0040 char *str = buf;
0041 int i;
0042
0043 for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
0044 i++) {
0045 if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
0046 continue;
0047 str +=
0048 sprintf(str, "%04x %02x\n", i,
0049 rdev->rswitch->route_table[i]);
0050 }
0051
0052 return (str - buf);
0053 }
0054 static DEVICE_ATTR_RO(routes);
0055
0056 static ssize_t lprev_show(struct device *dev,
0057 struct device_attribute *attr, char *buf)
0058 {
0059 struct rio_dev *rdev = to_rio_dev(dev);
0060
0061 return sprintf(buf, "%s\n",
0062 (rdev->prev) ? rio_name(rdev->prev) : "root");
0063 }
0064 static DEVICE_ATTR_RO(lprev);
0065
0066 static ssize_t lnext_show(struct device *dev,
0067 struct device_attribute *attr, char *buf)
0068 {
0069 struct rio_dev *rdev = to_rio_dev(dev);
0070 char *str = buf;
0071 int i;
0072
0073 if (rdev->pef & RIO_PEF_SWITCH) {
0074 for (i = 0; i < RIO_GET_TOTAL_PORTS(rdev->swpinfo); i++) {
0075 if (rdev->rswitch->nextdev[i])
0076 str += sprintf(str, "%s\n",
0077 rio_name(rdev->rswitch->nextdev[i]));
0078 else
0079 str += sprintf(str, "null\n");
0080 }
0081 }
0082
0083 return str - buf;
0084 }
0085 static DEVICE_ATTR_RO(lnext);
0086
0087 static ssize_t modalias_show(struct device *dev,
0088 struct device_attribute *attr, char *buf)
0089 {
0090 struct rio_dev *rdev = to_rio_dev(dev);
0091
0092 return sprintf(buf, "rapidio:v%04Xd%04Xav%04Xad%04X\n",
0093 rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did);
0094 }
0095 static DEVICE_ATTR_RO(modalias);
0096
0097 static struct attribute *rio_dev_attrs[] = {
0098 &dev_attr_did.attr,
0099 &dev_attr_vid.attr,
0100 &dev_attr_device_rev.attr,
0101 &dev_attr_asm_did.attr,
0102 &dev_attr_asm_vid.attr,
0103 &dev_attr_asm_rev.attr,
0104 &dev_attr_lprev.attr,
0105 &dev_attr_destid.attr,
0106 &dev_attr_modalias.attr,
0107
0108
0109 &dev_attr_routes.attr,
0110 &dev_attr_lnext.attr,
0111 &dev_attr_hopcount.attr,
0112 NULL,
0113 };
0114
0115 static ssize_t
0116 rio_read_config(struct file *filp, struct kobject *kobj,
0117 struct bin_attribute *bin_attr,
0118 char *buf, loff_t off, size_t count)
0119 {
0120 struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
0121 unsigned int size = 0x100;
0122 loff_t init_off = off;
0123 u8 *data = (u8 *) buf;
0124
0125
0126 if (capable(CAP_SYS_ADMIN))
0127 size = RIO_MAINT_SPACE_SZ;
0128
0129 if (off >= size)
0130 return 0;
0131 if (off + count > size) {
0132 size -= off;
0133 count = size;
0134 } else {
0135 size = count;
0136 }
0137
0138 if ((off & 1) && size) {
0139 u8 val;
0140 rio_read_config_8(dev, off, &val);
0141 data[off - init_off] = val;
0142 off++;
0143 size--;
0144 }
0145
0146 if ((off & 3) && size > 2) {
0147 u16 val;
0148 rio_read_config_16(dev, off, &val);
0149 data[off - init_off] = (val >> 8) & 0xff;
0150 data[off - init_off + 1] = val & 0xff;
0151 off += 2;
0152 size -= 2;
0153 }
0154
0155 while (size > 3) {
0156 u32 val;
0157 rio_read_config_32(dev, off, &val);
0158 data[off - init_off] = (val >> 24) & 0xff;
0159 data[off - init_off + 1] = (val >> 16) & 0xff;
0160 data[off - init_off + 2] = (val >> 8) & 0xff;
0161 data[off - init_off + 3] = val & 0xff;
0162 off += 4;
0163 size -= 4;
0164 }
0165
0166 if (size >= 2) {
0167 u16 val;
0168 rio_read_config_16(dev, off, &val);
0169 data[off - init_off] = (val >> 8) & 0xff;
0170 data[off - init_off + 1] = val & 0xff;
0171 off += 2;
0172 size -= 2;
0173 }
0174
0175 if (size > 0) {
0176 u8 val;
0177 rio_read_config_8(dev, off, &val);
0178 data[off - init_off] = val;
0179 off++;
0180 --size;
0181 }
0182
0183 return count;
0184 }
0185
0186 static ssize_t
0187 rio_write_config(struct file *filp, struct kobject *kobj,
0188 struct bin_attribute *bin_attr,
0189 char *buf, loff_t off, size_t count)
0190 {
0191 struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
0192 unsigned int size = count;
0193 loff_t init_off = off;
0194 u8 *data = (u8 *) buf;
0195
0196 if (off >= RIO_MAINT_SPACE_SZ)
0197 return 0;
0198 if (off + count > RIO_MAINT_SPACE_SZ) {
0199 size = RIO_MAINT_SPACE_SZ - off;
0200 count = size;
0201 }
0202
0203 if ((off & 1) && size) {
0204 rio_write_config_8(dev, off, data[off - init_off]);
0205 off++;
0206 size--;
0207 }
0208
0209 if ((off & 3) && (size > 2)) {
0210 u16 val = data[off - init_off + 1];
0211 val |= (u16) data[off - init_off] << 8;
0212 rio_write_config_16(dev, off, val);
0213 off += 2;
0214 size -= 2;
0215 }
0216
0217 while (size > 3) {
0218 u32 val = data[off - init_off + 3];
0219 val |= (u32) data[off - init_off + 2] << 8;
0220 val |= (u32) data[off - init_off + 1] << 16;
0221 val |= (u32) data[off - init_off] << 24;
0222 rio_write_config_32(dev, off, val);
0223 off += 4;
0224 size -= 4;
0225 }
0226
0227 if (size >= 2) {
0228 u16 val = data[off - init_off + 1];
0229 val |= (u16) data[off - init_off] << 8;
0230 rio_write_config_16(dev, off, val);
0231 off += 2;
0232 size -= 2;
0233 }
0234
0235 if (size) {
0236 rio_write_config_8(dev, off, data[off - init_off]);
0237 off++;
0238 --size;
0239 }
0240
0241 return count;
0242 }
0243
0244 static struct bin_attribute rio_config_attr = {
0245 .attr = {
0246 .name = "config",
0247 .mode = S_IRUGO | S_IWUSR,
0248 },
0249 .size = RIO_MAINT_SPACE_SZ,
0250 .read = rio_read_config,
0251 .write = rio_write_config,
0252 };
0253
0254 static struct bin_attribute *rio_dev_bin_attrs[] = {
0255 &rio_config_attr,
0256 NULL,
0257 };
0258
0259 static umode_t rio_dev_is_attr_visible(struct kobject *kobj,
0260 struct attribute *attr, int n)
0261 {
0262 struct rio_dev *rdev = to_rio_dev(kobj_to_dev(kobj));
0263 umode_t mode = attr->mode;
0264
0265 if (!(rdev->pef & RIO_PEF_SWITCH) &&
0266 (attr == &dev_attr_routes.attr ||
0267 attr == &dev_attr_lnext.attr ||
0268 attr == &dev_attr_hopcount.attr)) {
0269
0270
0271
0272 mode = 0;
0273 }
0274
0275 return mode;
0276 }
0277
0278 static const struct attribute_group rio_dev_group = {
0279 .attrs = rio_dev_attrs,
0280 .is_visible = rio_dev_is_attr_visible,
0281 .bin_attrs = rio_dev_bin_attrs,
0282 };
0283
0284 const struct attribute_group *rio_dev_groups[] = {
0285 &rio_dev_group,
0286 NULL,
0287 };
0288
0289 static ssize_t scan_store(struct bus_type *bus, const char *buf, size_t count)
0290 {
0291 long val;
0292 int rc;
0293
0294 if (kstrtol(buf, 0, &val) < 0)
0295 return -EINVAL;
0296
0297 if (val == RIO_MPORT_ANY) {
0298 rc = rio_init_mports();
0299 goto exit;
0300 }
0301
0302 if (val < 0 || val >= RIO_MAX_MPORTS)
0303 return -EINVAL;
0304
0305 rc = rio_mport_scan((int)val);
0306 exit:
0307 if (!rc)
0308 rc = count;
0309
0310 return rc;
0311 }
0312 static BUS_ATTR_WO(scan);
0313
0314 static struct attribute *rio_bus_attrs[] = {
0315 &bus_attr_scan.attr,
0316 NULL,
0317 };
0318
0319 static const struct attribute_group rio_bus_group = {
0320 .attrs = rio_bus_attrs,
0321 };
0322
0323 const struct attribute_group *rio_bus_groups[] = {
0324 &rio_bus_group,
0325 NULL,
0326 };
0327
0328 static ssize_t
0329 port_destid_show(struct device *dev, struct device_attribute *attr,
0330 char *buf)
0331 {
0332 struct rio_mport *mport = to_rio_mport(dev);
0333
0334 if (mport)
0335 return sprintf(buf, "0x%04x\n", mport->host_deviceid);
0336 else
0337 return -ENODEV;
0338 }
0339 static DEVICE_ATTR_RO(port_destid);
0340
0341 static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr,
0342 char *buf)
0343 {
0344 struct rio_mport *mport = to_rio_mport(dev);
0345
0346 if (mport)
0347 return sprintf(buf, "%u\n", mport->sys_size);
0348 else
0349 return -ENODEV;
0350 }
0351 static DEVICE_ATTR_RO(sys_size);
0352
0353 static struct attribute *rio_mport_attrs[] = {
0354 &dev_attr_port_destid.attr,
0355 &dev_attr_sys_size.attr,
0356 NULL,
0357 };
0358
0359 static const struct attribute_group rio_mport_group = {
0360 .attrs = rio_mport_attrs,
0361 };
0362
0363 const struct attribute_group *rio_mport_groups[] = {
0364 &rio_mport_group,
0365 NULL,
0366 };