|  | @@ -1,5 +1,5 @@
 | 
	
		
			
				|  |  |  /* aoeping.c - userland aoe pinger
 | 
	
		
			
				|  |  | - * Copyright 2008, Coraid, Inc., and licensed under GPL v.2.
 | 
	
		
			
				|  |  | + * Copyright 2009, CORAID, Inc., and licensed under GPL v.2.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   * run without arguments for usage
 | 
	
		
			
				|  |  |   */
 | 
	
	
		
			
				|  | @@ -210,8 +210,20 @@ pp_idtext(char *prefix, unsigned char *p, size_t len)
 | 
	
		
			
				|  |  |  	putchar('\n');
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +int smart_supported(unsigned char *p)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u16 w;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	p += 82 * 2;		/* skip to word 82 */
 | 
	
		
			
				|  |  | +	w = *p++;
 | 
	
		
			
				|  |  | +	w |= *p << 8;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* word 82 bit 0 is SMART support per ATA spec */
 | 
	
		
			
				|  |  | +	return !!(w & 1);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void
 | 
	
		
			
				|  |  | -disk_identify(Conf *c, u32 tag)
 | 
	
		
			
				|  |  | +disk_identify(Conf *c, struct progopts *opts, int *smart)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	int n;
 | 
	
		
			
				|  |  |  	uchar buf[1400];
 | 
	
	
		
			
				|  | @@ -219,7 +231,7 @@ disk_identify(Conf *c, u32 tag)
 | 
	
		
			
				|  |  |  	Ata *p;
 | 
	
		
			
				|  |  |  	struct hd_driveid *id;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	ata_prep(&a, c, tag);
 | 
	
		
			
				|  |  | +	ata_prep(&a, c, opts->tag);
 | 
	
		
			
				|  |  |  	a.sectors = 1;
 | 
	
		
			
				|  |  |  	a.cmd = ATAid_dev;
 | 
	
		
			
				|  |  |  	a.lba[3] = 0xa0;
 | 
	
	
		
			
				|  | @@ -229,15 +241,19 @@ disk_identify(Conf *c, u32 tag)
 | 
	
		
			
				|  |  |  		exit(EXIT_FAILURE);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	n = aoe_pkt_read(buf, sizeof buf, c, tag);
 | 
	
		
			
				|  |  | +	n = aoe_pkt_read(buf, sizeof buf, c, opts->tag);
 | 
	
		
			
				|  |  |  	p = (Ata *) buf;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if (!opts.pp_ataid) {
 | 
	
		
			
				|  |  | +	*smart = smart_supported(p->data);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (opts->ata_ident && !opts->pp_ataid) {
 | 
	
		
			
				|  |  |  		puts("device identify response:");
 | 
	
		
			
				|  |  |  		hex_print(stdout, p->data, 512, " ");
 | 
	
		
			
				|  |  |  		return;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +	if (!opts->pp_ataid)
 | 
	
		
			
				|  |  | +		return;
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  |  	for (n = 0; n < 1024; n += 2) {
 | 
	
		
			
				|  |  |  		unsigned char ch;
 | 
	
		
			
				|  |  |  		ch = p->data[n];
 | 
	
	
		
			
				|  | @@ -281,9 +297,15 @@ smart_registers(Ata *a, char *opts, struct smartcmd *s)
 | 
	
		
			
				|  |  |  		a->lba[0] = strtol(opts, NULL, 0);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  |  show_smart_regs(Ata *a)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | +	if (a->err & ATAabrt) {
 | 
	
		
			
				|  |  | +		fputs("SMART command aborted on target.\n",
 | 
	
		
			
				|  |  | +		      stderr);
 | 
	
		
			
				|  |  | +		return -1;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	puts("ATA registers:");
 | 
	
		
			
				|  |  |  	char *names[] = {
 | 
	
		
			
				|  |  |  		"Features", "Sector Count",
 | 
	
	
		
			
				|  | @@ -299,6 +321,8 @@ show_smart_regs(Ata *a)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	for (i = 0; i < sizeof regs / sizeof regs[0]; ++i)
 | 
	
		
			
				|  |  |  		printf("%20s: 0x%02x\n", names[i], regs[i]);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void
 | 
	
	
		
			
				|  | @@ -335,7 +359,8 @@ smart(Conf *c, u32 tag, char *smart_cmd)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	n = aoe_pkt_read(buf, sizeof buf, c, tag);
 | 
	
		
			
				|  |  |  	p = (Ata *) buf;
 | 
	
		
			
				|  |  | -	show_smart_regs(p);
 | 
	
		
			
				|  |  | +	if (show_smart_regs(p) != 0)
 | 
	
		
			
				|  |  | +		exit(EXIT_FAILURE);
 | 
	
		
			
				|  |  |  	if (s->data & SmartDataRet) {
 | 
	
		
			
				|  |  |  		puts("SMART data:");
 | 
	
		
			
				|  |  |  		hex_print(stdout, p->data, 512, " ");
 | 
	
	
		
			
				|  | @@ -416,6 +441,7 @@ int
 | 
	
		
			
				|  |  |  main(int argc, char *argv[])
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	Conf c;
 | 
	
		
			
				|  |  | +	int smartable = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	opts = defaults;
 | 
	
		
			
				|  |  |  	progname = strrchr(argv[0], '/');
 | 
	
	
		
			
				|  | @@ -448,14 +474,20 @@ main(int argc, char *argv[])
 | 
	
		
			
				|  |  |  		fflush(stdout);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if (opts.ata_ident) {
 | 
	
		
			
				|  |  | +	if (opts.ata_ident || opts.smart) {
 | 
	
		
			
				|  |  |  		alarm(opts.timeout);
 | 
	
		
			
				|  |  | -		disk_identify(&c, opts.tag);
 | 
	
		
			
				|  |  | +		disk_identify(&c, &opts, &smartable);
 | 
	
		
			
				|  |  |  		alarm(0);
 | 
	
		
			
				|  |  |  		opts.tag += 1;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (opts.smart) {
 | 
	
		
			
				|  |  | +		if (!smartable) {
 | 
	
		
			
				|  |  | +			fprintf(stderr,
 | 
	
		
			
				|  |  | +				"Error: e%d.%d does not support SMART\n",
 | 
	
		
			
				|  |  | +				ntohs(c.h.maj), c.h.min);
 | 
	
		
			
				|  |  | +			exit(EXIT_FAILURE);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  		alarm(opts.timeout);
 | 
	
		
			
				|  |  |  		smart(&c, opts.tag, opts.smart);
 | 
	
		
			
				|  |  |  		alarm(0);
 |