1/* 2 * Copyright 2004-2006, Haiku, Inc. All RightsReserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <SupportDefs.h> 8 9#include <errno.h> 10#include <fcntl.h> 11#include <stdio.h> 12#include <string.h> 13 14// This one comes from Thomas Kurschel's IDE bus manager. 15#include "ide_device_infoblock.h" 16 17extern const char *__progname; 18 19/* why isn't that documented ? */ 20#define IDE_GET_INFO 0x2710 21#define IDE_GET_STATUS 0x2711 22 23typedef struct { 24 uint8 dummy; 25 uint8 dma_status; 26 uint8 pio_mode; 27 uint8 dma_mode; 28} _PACKED ide_status_t; 29 30 31#define kNotSupported "not supported" 32#define kSupported "supported" 33 34char *dma_mode_strings[] = { 35 "Multiword DMA Mode 0 - 4.2 MB/s", 36 "Multiword DMA Mode 1 - 13.3 MB/s", 37 "Multiword DMA Mode 2 - 16.7 MB/s", 38 "Invalid", 39 "Invalid", 40 "Invalid", 41 "Invalid", 42 "Invalid", 43 "Invalid", 44 "Invalid", 45 "Invalid", 46 "Invalid", 47 "Invalid", 48 "Invalid", 49 "Invalid", 50 "Invalid", 51 "Ultra DMA Mode 0 - 16.7 MB/s", 52 "Ultra DMA Mode 1 - 25 MB/s", 53 "Ultra DMA Mode 2 - 33.3 MB/s", 54 "Ultra DMA Mode 3 - 44.4 MB/s", 55 "Ultra DMA Mode 4 - 66.7 MB/s", 56 "Ultra DMA Mode 5 - 100 MB/s", 57 "Ultra DMA Mode 6 - 133 MB/s" 58}; 59 60static void 61sizeAsString(off_t size, char *string) 62{ 63 double kb = size / 1024.0; 64 float mb, gb, tb; 65 if (kb < 1.0) { 66 sprintf(string, "%Ld B", size); 67 return; 68 } 69 mb = kb / 1024.0; 70 if (mb < 1.0) { 71 sprintf(string, "%3.1f KB", kb); 72 return; 73 } 74 gb = mb / 1024.0; 75 if (gb < 1.0) { 76 sprintf(string, "%3.1f MB", mb); 77 return; 78 } 79 tb = gb / 1024.0; 80 if (tb < 1.0) { 81 sprintf(string, "%3.1f GB", gb); 82 return; 83 } 84 sprintf(string, "%.1f TB", tb); 85} 86 87 88int 89main(int argc, char **argv) 90{ 91 int fd; 92 ide_device_infoblock ide_info; 93 off_t capacity = 0; 94 char capacityString[20]; 95 bool removable; 96 97 if (argc < 2) { 98 fprintf(stderr, "usage: %s <device>\n", __progname); 99 return 1; 100 } 101 102 fd = open(argv[1], O_RDONLY); 103 if (fd < 0) { 104 fprintf(stderr, "could not open %s: %s\n", argv[1], strerror(errno)); 105 return 2; 106 } 107 108 if (ioctl(fd, IDE_GET_INFO, &ide_info, sizeof(ide_device_infoblock)) < 0) { 109 fprintf(stderr, "could not get ide info for %s\n", argv[1]); 110 return 3; 111 } 112 113 printf("Model Number: %.40s\n", ide_info.model_number); 114 printf("Serial Number: %.20s\n", ide_info.serial_number); 115 printf("Firmware Version: %.8s\n", ide_info.firmware_version); 116 printf("\n"); 117 118 if (ide_info._48_bit_addresses_supported) { 119 capacity = ide_info.LBA48_total_sectors * 512LL; 120 } else if (ide_info.LBA_supported) { 121 capacity = ide_info.LBA_total_sectors * 512LL; 122 } else { 123 capacity = (ide_info.cylinders * ide_info.heads * 124 ide_info.sectors) * 512LL; 125 } 126 127 sizeAsString(capacity, capacityString); 128 printf("Capacity: %s\n", capacityString); 129 printf("LBA supported: %s\n", ide_info.LBA_supported ? "yes" : "no"); 130 printf("\n"); 131 132 printf("DMA supported: %s\n", ide_info.DMA_supported ? "yes" : "no"); 133 134 if (ide_info.DMA_supported) { 135 ide_status_t st = {0x01, 0x00, 0x00, 0x80}; /* God knows... */ 136 137 if (ioctl(fd, IDE_GET_STATUS, &st, sizeof(ide_status_t *)) < 0) { 138 fprintf(stderr, "could not get ide status for %s\n", argv[1]); 139 return 3; 140 } 141 142 if (st.dma_status > 6) 143 printf("Bad dma_status field\n"); 144 else 145 printf("DMA mode: %s\n", dma_mode_strings[st.dma_mode]); 146 } 147 148 printf("READ/WRITE DMA QUEUED: %s\n", 149 ide_info.DMA_QUEUED_supported ? kSupported : kNotSupported); 150 printf("\n"); 151 152 printf("Write Cache: %s\n", 153 ide_info.write_cache_supported ? kSupported : kNotSupported); 154 printf("Look Ahead: %s\n", 155 ide_info.look_ahead_supported ? kSupported : kNotSupported); 156 printf("Bus Release IRQ: %s\n", 157 ide_info.RELEASE_irq_supported ? kSupported : kNotSupported); 158 printf("Service start transfer IRQ: %s\n", 159 ide_info.SERVICE_irq_supported ? kSupported : kNotSupported); 160 printf("NOP: %s\n", 161 ide_info.NOP_supported ? kSupported : kNotSupported); 162 printf("FLUSH CACHE: %s\n", 163 ide_info.FLUSH_CACHE_supported ? kSupported : kNotSupported); 164 printf("FLUSH CACHE EXT: %s\n", 165 ide_info.FLUSH_CACHE_EXT_supported ? kSupported : kNotSupported); 166 printf("\n"); 167 168 printf("CFA features: %s\n", 169 ide_info.CFA_supported ? kSupported : kNotSupported); 170 171 removable = ide_info._0.ata.removable_media || 172 ide_info._0.atapi.removable_media; 173 174 printf("Removable: %s\n", removable ? "yes" : "no"); 175 176 printf("Removable Media State Notification features: %s\n", 177 (ide_info._127_RMSN_support == 1) ? kSupported : kNotSupported); 178 printf("\n"); 179 180 // Not in original ideinfo: 181 printf("Microcode download: %s\n", 182 ide_info.DOWNLOAD_MICROCODE_supported ? kSupported : kNotSupported); 183 printf("S.M.A.R.T: %s\n", 184 ide_info.SMART_supported ? kSupported : kNotSupported); 185 printf("Power Management: %s\n", 186 ide_info.PM_supported ? kSupported : kNotSupported); 187 printf("\n"); 188 189 // TODO: where do we find these fields? 190/* 191 printf("Statistics (for entire IDE bus)\n"); 192 printf("Overlappable commands: %d\n", ide_info.); 193 printf("Started as overlapped: %d\n", ide_info.); 194 printf("Started as non-overlapped: %d\n", ide_info.); 195 printf("Average queue depth (of overlapped commands): %d\n", ide_info.); 196 printf("Non-Overlappable commands: %d\n", ide_info.); 197 printf("Bus released by device: %d\n", ide_info.); 198*/ 199 200 close(fd); 201 return 0; 202} 203