1/* 2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval 7 */ 8 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <unistd.h> 14 15#include <drivers/device_manager.h> 16#include <drivers/module.h> 17#include <drivers/PCI.h> 18#include <drivers/bus/PCI.h> 19#include <drivers/bus/SCSI.h> 20 21#include "dm_wrapper.h" 22#include "pcihdr.h" 23#include "pci-utils.h" 24 25 26extern const char *__progname; 27 28#define DUMP_MODE 0 29#define USER_MODE 1 30int gMode = USER_MODE; 31 32#define BUS_ISA 1 33#define BUS_PCI 2 34#define BUS_SCSI 3 35 36 37static const char * 38get_scsi_device_type(uint8 type) 39{ 40 switch (type) { 41 case 0x0: return "Direct Access"; 42 case 0x1: return "Sequential Access"; 43 case 0x2: return "Printer"; 44 case 0x3: return "Processor"; 45 case 0x4: return "WORM"; 46 case 0x5: return "CDROM"; 47 case 0x6: return "Scanner"; 48 case 0x7: return "Optical memory"; 49 case 0x8: return "Medium changer"; 50 case 0x9: return "Communication"; 51 case 0xc: return "Storage array controller"; 52 case 0xd: return "Enclosure services"; 53 case 0xe: return "Simplified Direct Access"; 54 default: return ""; 55 } 56} 57 58 59static void 60usage() 61{ 62 fprintf(stderr, "usage: %s [-d]\n", __progname); 63 fprintf(stderr, "Displays devices in a user friendly way\n"); 64 fprintf(stderr, "-d : dumps the tree\n"); 65 exit(0); 66} 67 68 69static void 70put_level(int32 level) 71{ 72 while (level-- > 0) 73 printf(" "); 74} 75 76 77static void 78dump_attribute(struct device_attr_info *attr, int32 level) 79{ 80 if (attr == NULL) 81 return; 82 83 put_level(level); 84 printf("\"%s\" : ", attr->name); 85 switch (attr->type) { 86 case B_STRING_TYPE: 87 printf("string : \"%s\"", attr->value.string); 88 break; 89 case B_UINT8_TYPE: 90 printf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8, 91 attr->value.ui8); 92 break; 93 case B_UINT16_TYPE: 94 printf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16, 95 attr->value.ui16); 96 break; 97 case B_UINT32_TYPE: 98 printf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32, 99 attr->value.ui32); 100 break; 101 case B_UINT64_TYPE: 102 printf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64, 103 attr->value.ui64); 104 break; 105 default: 106 printf("raw data"); 107 } 108 printf("\n"); 109} 110 111 112static void 113dump_device(device_node_cookie *node, uint8 level) 114{ 115 char data[256]; 116 struct device_attr_info attr; 117 attr.cookie = 0; 118 attr.node_cookie = *node; 119 attr.value.raw.data = data; 120 attr.value.raw.length = sizeof(data); 121 122 put_level(level); 123 printf("(%d)\n", level); 124 while (dm_get_next_attr(&attr) == B_OK) { 125 dump_attribute(&attr, level); 126 } 127} 128 129 130static void 131dump_nodes(device_node_cookie *node, uint8 level) 132{ 133 status_t err; 134 device_node_cookie child = *node; 135 dump_device(node, level); 136 137 if (get_child(&child) != B_OK) 138 return; 139 140 do { 141 dump_nodes(&child, level + 1); 142 } while ((err = get_next_child(&child)) == B_OK); 143 144} 145 146 147static int32 148display_device(device_node_cookie *node, uint8 level) 149{ 150 uint8 new_level = level; 151 152 char data[256]; 153 struct device_attr_info attr; 154 155 // BUS attributes 156 char device_bus[64]; 157 uint8 scsi_path_id = 255; 158 int bus = 0; 159 160 // PCI attributes 161 uint8 pci_class_base_id = 0; 162 uint8 pci_class_sub_id = 0; 163 uint8 pci_class_api_id = 0; 164 uint16 pci_vendor_id = 0; 165 uint16 pci_device_id = 0; 166 uint16 pci_subsystem_vendor_id = 0; 167 uint16 pci_subsystem_id = 0; 168 169 // SCSI attributes 170 uint8 scsi_target_lun = 0; 171 uint8 scsi_target_id = 0; 172 uint8 scsi_type = 255; 173 char scsi_vendor[64]; 174 char scsi_product[64]; 175 176 const char *venShort; 177 const char *venFull; 178 const char *devShort; 179 const char *devFull; 180 181 attr.cookie = 0; 182 attr.node_cookie = *node; 183 attr.value.raw.data = data; 184 attr.value.raw.length = sizeof(data); 185 186 while (dm_get_next_attr(&attr) == B_OK) { 187 if (!strcmp(attr.name, B_DEVICE_BUS) 188 && attr.type == B_STRING_TYPE) { 189 strlcpy(device_bus, attr.value.string, 64); 190 } else if (!strcmp(attr.name, "scsi/path_id") 191 && attr.type == B_UINT8_TYPE) { 192 scsi_path_id = attr.value.ui8; 193 } else if (!strcmp(attr.name, B_DEVICE_TYPE) 194 && attr.type == B_UINT16_TYPE) 195 pci_class_base_id = attr.value.ui8; 196 else if (!strcmp(attr.name, B_DEVICE_SUB_TYPE) 197 && attr.type == B_UINT16_TYPE) 198 pci_class_sub_id = attr.value.ui8; 199 else if (!strcmp(attr.name, B_DEVICE_INTERFACE) 200 && attr.type == B_UINT16_TYPE) 201 pci_class_api_id = attr.value.ui8; 202 else if (!strcmp(attr.name, B_DEVICE_VENDOR_ID) 203 && attr.type == B_UINT16_TYPE) 204 pci_vendor_id = attr.value.ui16; 205 else if (!strcmp(attr.name, B_DEVICE_ID) 206 && attr.type == B_UINT16_TYPE) 207 pci_device_id = attr.value.ui16; 208 else if (!strcmp(attr.name, SCSI_DEVICE_TARGET_LUN_ITEM) 209 && attr.type == B_UINT8_TYPE) 210 scsi_target_lun = attr.value.ui8; 211 else if (!strcmp(attr.name, SCSI_DEVICE_TARGET_ID_ITEM) 212 && attr.type == B_UINT8_TYPE) 213 scsi_target_id = attr.value.ui8; 214 else if (!strcmp(attr.name, SCSI_DEVICE_TYPE_ITEM) 215 && attr.type == B_UINT8_TYPE) 216 scsi_type = attr.value.ui8; 217 else if (!strcmp(attr.name, SCSI_DEVICE_VENDOR_ITEM) 218 && attr.type == B_STRING_TYPE) 219 strlcpy(scsi_vendor, attr.value.string, 64); 220 else if (!strcmp(attr.name, SCSI_DEVICE_PRODUCT_ITEM) 221 && attr.type == B_STRING_TYPE) 222 strlcpy(scsi_product, attr.value.string, 64); 223 224 if (!strcmp(device_bus, "isa")) 225 bus = BUS_ISA; 226 else if (!strcmp(device_bus, "pci")) 227 bus = BUS_PCI; 228 else if (scsi_path_id < 255) 229 bus = BUS_SCSI; 230 231 /*else if (!strcmp(attr.name, PCI_DEVICE_SUBVENDOR_ID_ITEM) 232 && attr.type == B_UINT16_TYPE) 233 pci_subsystem_vendor_id = attr.value.ui16; 234 else if (!strcmp(attr.name, PCI_DEVICE_SUBSYSTEM_ID_ITEM) 235 && attr.type == B_UINT16_TYPE) 236 pci_subsystem_id = attr.value.ui16;*/ 237 238 attr.value.raw.data = data; 239 attr.value.raw.length = sizeof(data); 240 } 241 242 switch (bus) { 243 case BUS_ISA: 244 new_level = level + 1; 245 break; 246 case BUS_PCI: 247 printf("\n"); 248 { 249 char classInfo[64]; 250 get_class_info(pci_class_base_id, pci_class_sub_id, 251 pci_class_api_id, classInfo, 64); 252 put_level(level); 253 printf("device %s [%x|%x|%x]\n", classInfo, pci_class_base_id, 254 pci_class_sub_id, pci_class_api_id); 255 } 256 257 put_level(level); 258 printf(" "); 259 get_vendor_info(pci_vendor_id, &venShort, &venFull); 260 if (!venShort && !venFull) { 261 printf("vendor %04x: Unknown\n", pci_vendor_id); 262 } else if (venShort && venFull) { 263 printf("vendor %04x: %s - %s\n", pci_vendor_id, 264 venShort, venFull); 265 } else { 266 printf("vendor %04x: %s\n", pci_vendor_id, 267 venShort ? venShort : venFull); 268 } 269 270 put_level(level); 271 printf(" "); 272 get_device_info(pci_vendor_id, pci_device_id, 273 pci_subsystem_vendor_id, pci_subsystem_id, &devShort, &devFull); 274 if (!devShort && !devFull) { 275 printf("device %04x: Unknown\n", pci_device_id); 276 } else if (devShort && devFull) { 277 printf("device %04x: %s (%s)\n", pci_device_id, 278 devShort, devFull); 279 } else { 280 printf("device %04x: %s\n", pci_device_id, 281 devShort ? devShort : devFull); 282 } 283 new_level = level + 1; 284 break; 285 case BUS_SCSI: 286 if (scsi_type == 255) 287 break; 288 put_level(level); 289 printf(" device [%x|%x]\n", scsi_target_id, scsi_target_lun); 290 put_level(level); 291 printf(" vendor %15s\tmodel %15s\ttype %s\n", scsi_vendor, 292 scsi_product, get_scsi_device_type(scsi_type)); 293 294 new_level = level + 1; 295 break; 296 } 297 298 return new_level; 299} 300 301 302static void 303display_nodes(device_node_cookie *node, uint8 level) 304{ 305 status_t err; 306 device_node_cookie child = *node; 307 level = display_device(node, level); 308 309 if (get_child(&child) != B_OK) 310 return; 311 312 do { 313 display_nodes(&child, level); 314 } while ((err = get_next_child(&child)) == B_OK); 315} 316 317 318int 319main(int argc, char **argv) 320{ 321 status_t error; 322 device_node_cookie root; 323 324 if ((error = init_dm_wrapper()) < 0) { 325 printf("Error initializing device manager (%s)\n", strerror(error)); 326 return error; 327 } 328 329 if (argc > 2) 330 usage(); 331 332 if (argc == 2) { 333 if (!strcmp(argv[1], "-d")) { 334 gMode = DUMP_MODE; 335 } else { 336 usage(); 337 } 338 } 339 340 if (gMode == DUMP_MODE) { 341 get_root(&root); 342 dump_nodes(&root, 0); 343 } else { 344 get_root(&root); 345 display_nodes(&root, 0); 346 } 347 348 uninit_dm_wrapper(); 349 350 return 0; 351} 352