Browse Source

Merge upstream version 10

David Martínez Moreno 18 years ago
parent
commit
e598a17956
14 changed files with 429 additions and 16 deletions
  1. 29 0
      NEWS
  2. 6 1
      README
  3. 18 9
      aoe.c
  4. 6 1
      ata.c
  5. 1 0
      config.h
  6. 2 0
      config/config.h.in
  7. 8 0
      config/u64.c
  8. 8 1
      dat.h
  9. 2 0
      fns.h
  10. 315 0
      freebsd.c
  11. 12 0
      linux.c
  12. 21 3
      makefile
  13. BIN
      vblade
  14. 1 1
      vbladed

+ 29 - 0
NEWS

@@ -1,4 +1,33 @@
 -*- change-log -*-
 -*- change-log -*-
+
+2005-12-06 Ed L. Cashin <ecashin@coraid.com>
+	fix u64 configuration on FreeBSD
+	release vblade-10
+	
+2005-12-06 Valeriy Glushkov <valery@rocketdivision.com>
+	implemented config string support
+	added handler for ATA Check power mode command
+	
+2005-11-15 Ed L. Cashin <ecashin@coraid.com>
+	add compatibility with platforms lacking u64 (e.g., Slackware)
+	release vblade-9
+	
+2005-11-10 Ed L. Cashin <ecashin@coraid.com>
+	call atainit on program startup
+	put VBLADE_VERSION in dat.h and use it in firmware version
+	release vblade-7
+	include Stacey's patch to use p{read,write} on FreeBSD
+	include Stacey's patch to typedef ulong on FreeBSD
+	fix makefile dependencies (e.g., rebuild on new aoe.c)
+	fix config string length specification
+	include Stacey's patch to avoid compile warnings on FreeBSD
+	release vblade-8
+	
+2005-11-10 "Stacey D. Son" <sson@verio.net>
+	include FreeBSD support
+	
+2005-10-03 Ed L. Cashin <ecashin@coraid.com>
+	don't invoke vblade with dash from vbladed
 	
 	
 2005-08-31 20:14:12 GMT Ed L. Cashin <ecashin@coraid.com>
 2005-08-31 20:14:12 GMT Ed L. Cashin <ecashin@coraid.com>
 	ATA identify: don't juggle bytes in shorts on big endian arch
 	ATA identify: don't juggle bytes in shorts on big endian arch

+ 6 - 1
README

@@ -12,10 +12,15 @@ The Linux aoe driver for the 2.6 kernel is compatible if you use
 aoe-2.6-7 or newer.  You can use older aoe drivers but you will only
 aoe-2.6-7 or newer.  You can use older aoe drivers but you will only
 be able to see one vblade per MAC address.
 be able to see one vblade per MAC address.
 
 
-The following command should build the vblade program:
+The following command should build the vblade program on a Linux-based
+system:
 
 
   make
   make
 
 
+For FreeBSD systems, include an extra parameter like so:
+
+  make PLATFORM=freebsd
+
 There is a "vbladed" script that daemonizes the program and sends its
 There is a "vbladed" script that daemonizes the program and sends its
 output to the logger program.  Make sure you have logger installed if
 output to the logger program.  Make sure you have logger installed if
 you would like to run vblade as a daemon with the vbladed script.
 you would like to run vblade as a daemon with the vbladed script.

+ 18 - 9
aoe.c

@@ -10,17 +10,25 @@
 #include "dat.h"
 #include "dat.h"
 #include "fns.h"
 #include "fns.h"
 
 
-// dummy for testing
+char cfg_str[1024];
+int cfg_str_len = 0;
+
 int
 int
 qcget(uchar *p, int len)
 qcget(uchar *p, int len)
 {
 {
-	memset(p, 0xff, len);
+	if (len > cfg_str_len)
+		len = cfg_str_len;
+	memcpy(p, cfg_str, len);
 	return len;
 	return len;
 }
 }
 
 
 int
 int
 qcset(uchar *p, int len)
 qcset(uchar *p, int len)
 {
 {
+	if (len > sizeof(cfg_str))
+		len = sizeof(cfg_str);
+	memcpy(cfg_str, p, len);
+	cfg_str_len = len;
 	return len;
 	return len;
 }
 }
 
 
@@ -45,8 +53,8 @@ aoead(int fd)			// advertise the virtual blade
 	p->vercmd = 0x10 | Qread;
 	p->vercmd = 0x10 | Qread;
 	len = qcget(p->data, 1024);
 	len = qcget(p->data, 1024);
 	p->len = htons(len);
 	p->len = htons(len);
-	if (write(fd, buf, len) == -1)
-		perror("write aoe id");
+	if (putpkt(fd, buf, sizeof *p - sizeof p->data + len) == -1)
+		perror("putpkt aoe id");
 }
 }
 
 
 int
 int
@@ -118,12 +126,12 @@ confcmd(Conf *p)	// process conf request
 		p->len = htons(len);
 		p->len = htons(len);
 		break;
 		break;
 	case Qset:
 	case Qset:
-		if (qcget(buf, 1024) > 0) {
+		len = qcget(buf, 1024);
+		if (len > 0 && (len != p->len || memcmp(buf, p->data, len))) {
 			p->h.flags |= Error;
 			p->h.flags |= Error;
 			p->h.error = ConfigErr;
 			p->h.error = ConfigErr;
 			break;
 			break;
 		}
 		}
-		len = 1024;
 		// fall thru
 		// fall thru
 	case Qfset:
 	case Qfset:
 		len = ntohs(p->len);
 		len = ntohs(p->len);
@@ -135,7 +143,7 @@ confcmd(Conf *p)	// process conf request
 	p->bufcnt = htons(Bufcount);
 	p->bufcnt = htons(Bufcount);
 	p->firmware = htons(FWV);
 	p->firmware = htons(FWV);
 	p->vercmd |= 0x10;
 	p->vercmd |= 0x10;
-	return len;
+	return len + sizeof(Conf) - 1024;
 }
 }
 
 
 void
 void
@@ -161,7 +169,7 @@ doaoe(Aoehdr *p)
 	p->maj = htons(shelf);
 	p->maj = htons(shelf);
 	p->min = slot;
 	p->min = slot;
 	p->flags |= Resp;
 	p->flags |= Resp;
-	if (write(sfd, p, len) == -1) {
+	if (putpkt(sfd, (uchar *) p, len) == -1) {
 		perror("write to network");
 		perror("write to network");
 		exit(1);
 		exit(1);
 	}
 	}
@@ -177,7 +185,7 @@ aoe(void)
 	aoead(sfd);
 	aoead(sfd);
 
 
 	for (;;) {
 	for (;;) {
-		n = read(sfd, buf, sizeof buf);
+		n = getpkt(sfd, buf, sizeof buf);
 		if (n < 0) {
 		if (n < 0) {
 			perror("read network");
 			perror("read network");
 			exit(1);
 			exit(1);
@@ -210,6 +218,7 @@ int
 main(int argc, char **argv)
 main(int argc, char **argv)
 {
 {
 	setbuf(stdin, NULL);
 	setbuf(stdin, NULL);
+	atainit();
 	progname = *argv;
 	progname = *argv;
 	if (argc != 5)
 	if (argc != 5)
 		usage();
 		usage();

+ 6 - 1
ata.c

@@ -86,7 +86,7 @@ atainit(void)
 	char buf[64];
 	char buf[64];
 
 
 	setfld(ident, 27, 40, "Coraid EtherDrive vblade");
 	setfld(ident, 27, 40, "Coraid EtherDrive vblade");
-	sprintf(buf, "V%d.%d\n", 4, 0);
+	sprintf(buf, "V%d\n", VBLADE_VERSION);
 	setfld(ident, 23, 8, buf);
 	setfld(ident, 23, 8, buf);
 	setfld(ident, 10, 20, "SSN HERE");
 	setfld(ident, 10, 20, "SSN HERE");
 }
 }
@@ -127,6 +127,11 @@ atacmd(Ataregs *p, uchar *dp)		// do the ata cmd
 		p->err = 0;
 		p->err = 0;
 		p->status = DRDY;
 		p->status = DRDY;
 		return;
 		return;
+	case 0xe5:		// check power mode
+		p->err = 0;
+		p->sectors = 0xff; // the device is active or idle
+		p->status = DRDY;
+		return;
 	default:
 	default:
 		p->status = DRDY | ERR;
 		p->status = DRDY | ERR;
 		p->err = ABRT;
 		p->err = ABRT;

+ 1 - 0
config.h

@@ -1 +1,2 @@
 #define _FILE_OFFSET_BITS 64 
 #define _FILE_OFFSET_BITS 64 
+typedef unsigned long long u64;

+ 2 - 0
config/config.h.in

@@ -0,0 +1,2 @@
+#define _FILE_OFFSET_BITS 64 
+//u64 typedef unsigned long long u64;

+ 8 - 0
config/u64.c

@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main(void)
+{
+	u64 n;
+	printf("%d\n", (int) n+2);
+	return 0;
+}

+ 8 - 1
dat.h

@@ -6,7 +6,10 @@
  */
  */
 
 
 enum {
 enum {
-	FWV			= 0x4000,		// Firmware version
+	VBLADE_VERSION		= 10,
+
+	// Firmware version
+	FWV			= 0x4000 + VBLADE_VERSION,
 };
 };
 
 
 #undef major
 #undef major
@@ -19,7 +22,11 @@ enum {
 
 
 typedef unsigned char uchar;
 typedef unsigned char uchar;
 //typedef unsigned short ushort;
 //typedef unsigned short ushort;
+#ifdef __FreeBSD__
+typedef unsigned long ulong;
+#else
 //typedef unsigned long ulong;
 //typedef unsigned long ulong;
+#endif
 typedef long long vlong;
 typedef long long vlong;
 
 
 typedef struct Aoehdr Aoehdr;
 typedef struct Aoehdr Aoehdr;

+ 2 - 0
fns.h

@@ -22,4 +22,6 @@ int	dial(char *);
 int	getea(int, char *, uchar *);
 int	getea(int, char *, uchar *);
 int	putsec(int, uchar *, vlong, int);
 int	putsec(int, uchar *, vlong, int);
 int	getsec(int, uchar *, vlong, int);
 int	getsec(int, uchar *, vlong, int);
+int	putpkt(int, uchar *, int);
+int	getpkt(int, uchar *, int);
 vlong	getsize(int);
 vlong	getsize(int);

+ 315 - 0
freebsd.c

@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2005, Stacey Son <sson (at) verio (dot) net>
+ * All rights reserved.
+ */
+
+// freebsd.c: low level access routines for FreeBSD
+#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <net/ethernet.h>
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <sys/stat.h>
+#include <sys/disklabel.h>
+#include <sys/select.h>
+#include <sys/sysctl.h>
+
+#include <fcntl.h>
+#include <errno.h>
+
+#include "dat.h"
+#include "fns.h"
+
+#define BPF_DEV "/dev/bpf0"
+
+/* Packet buffer for getpkt() */
+static uchar *pktbuf = NULL;
+static int pktbufsz = 0;
+
+int
+dial(char *eth)
+{
+	char m;
+	int fd = -1;
+	struct bpf_version bv;
+	u_int v;
+	unsigned bufsize, linktype;
+	char device[sizeof BPF_DEV];
+	struct ifreq ifr;
+
+	/* packet filter for bpf */
+	struct bpf_insn bpf_insns[] = {
+	  /* Load the type into register */
+	  BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
+	  /* Does it match AoE Type (0x88a2)? No, goto INVALID */
+	  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x88a2, 0, 10),
+	  /* Load the flags into register */
+	  BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 14),
+	  /* Check to see if the Resp flag is set */
+	  BPF_STMT(BPF_ALU+BPF_AND+BPF_K, Resp),
+	  /* Yes, goto INVALID */
+	  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 7),
+	  /* Load the command into register */
+	  BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 19),
+	  /* Is this a ATAcmd? No, goto VALID */
+	  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ATAcmd, 0, 4),
+	  /* Load the shelf number into register */
+	  BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16),
+	  /* Does it match shelf number? No, goto INVALID */
+	  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (u_int) shelf, 0, 3),
+	  /* Load the slot number into register */
+	  BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18),
+	  /* Does it match shelf number? No, goto INVALID */
+	  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (u_int) slot, 0, 1),
+	  /* VALID: return -1 (allow the packet to be read) */
+	  BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+	  /* INVALID: return 0 (ignore the packet) */
+	  BPF_STMT(BPF_RET+BPF_K, 0),
+	};
+
+	struct bpf_program bpf_program = {
+	  sizeof(bpf_insns)/sizeof(struct bpf_insn),
+	  bpf_insns
+	};
+
+
+	strncpy(device, BPF_DEV, sizeof BPF_DEV);
+
+	/* find a bpf device we can use, check /dev/bpf[0-9] */
+	for (m = '0'; m <= '9'; m++) {
+		device[sizeof(BPF_DEV)-2] = m;
+
+		if ((fd = open(device, O_RDWR)) > 0)
+			break;
+	}
+
+	if (fd < 0) {
+		perror("open");
+		return -1;
+	}
+
+	if (ioctl(fd, BIOCVERSION, &bv) < 0) {
+		perror("BIOCVERSION");
+		goto bad;
+	}
+
+	if (bv.bv_major != BPF_MAJOR_VERSION ||
+	    bv.bv_minor < BPF_MINOR_VERSION) {
+		fprintf(stderr,
+			"kernel bpf filter out of date\n");
+		goto bad;
+	}
+
+	/*
+	 * Try finding a good size for the buffer; 65536 may be too
+	 * big, so keep cutting it in half until we find a size
+	 * that works, or run out of sizes to try.
+	 *
+	 */
+	for (v = 65536; v != 0; v >>= 1) {
+		(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
+
+		(void)strncpy(ifr.ifr_name, eth,
+			sizeof(ifr.ifr_name));
+		if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
+			break;  /* that size worked; we're done */
+
+		if (errno != ENOBUFS) {
+			fprintf(stderr, "BIOCSETIF: %s: %s\n",
+					eth, strerror(errno));
+			goto bad;
+		}
+	}
+	if (v == 0) {
+		fprintf(stderr, 
+			"BIOCSBLEN: %s: No buffer size worked\n", eth);
+		goto bad;
+	}
+
+	/* Allocate memory for the packet buffer */
+	pktbufsz = v;
+	if ((pktbuf = malloc(pktbufsz)) == NULL) {
+		perror("malloc");
+		goto bad;
+	}
+
+	/* Don't wait for buffer to be full or timeout */
+	v = 1;
+	if (ioctl(fd, BIOCIMMEDIATE, &v) < 0) {
+		perror("BIOCIMMEDIATE");
+		goto bad;
+	}
+
+	/* Only read incoming packets */
+	v = 0;
+	if (ioctl(fd, BIOCSSEESENT, &v) < 0) {
+		perror("BIOCSSEESENT");
+		goto bad;
+	}
+
+	/* Don't complete ethernet hdr */
+	v = 1;
+	if (ioctl(fd, BIOCSHDRCMPLT, &v) < 0) {
+		perror("BIOCSHDRCMPLT");
+		goto bad;
+	}
+
+	/* Get the data link layer type. */
+	if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
+		perror("BIOCGDLT");
+		goto bad;
+	}
+	linktype = v;
+
+	/* Get the filter buf size */
+	if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
+		perror("BIOCGBLEN");
+		goto bad;
+	}
+	bufsize = v;
+
+	if (ioctl(fd, BIOCSETF, (caddr_t)&bpf_program) < 0) {
+		perror("BIOSETF");
+		goto bad;
+	} 
+
+	return(fd);
+
+bad:
+	close(fd);
+	return(-1);
+}
+
+int
+getea(int s, char *eth, uchar *ea)
+{
+	int mib[6];
+	size_t len;
+	char *buf, *next, *end;
+	struct if_msghdr *ifm;
+	struct sockaddr_dl *sdl;
+	
+
+	mib[0] = CTL_NET; 	mib[1] = AF_ROUTE;
+	mib[2] = 0; 		mib[3] = AF_LINK;
+	mib[4] = NET_RT_IFLIST;	mib[5] = 0;
+
+	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
+		return (-1);
+	}
+
+	if (!(buf = (char *) malloc(len))) {
+		return (-1);
+	}
+	
+	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+		free(buf);
+		return (-1);
+	}
+	end = buf + len;
+
+	for (next = buf; next < end; next += ifm->ifm_msglen) {
+		ifm = (struct if_msghdr *)next;
+		if (ifm->ifm_type == RTM_IFINFO) {
+			sdl = (struct sockaddr_dl *)(ifm + 1);
+			if (strncmp(&sdl->sdl_data[0], eth, 
+					sdl->sdl_nlen) == 0) {
+				memcpy(ea, LLADDR(sdl), ETHER_ADDR_LEN);
+				break;
+			}
+
+		}
+
+	}
+
+	free(buf);
+	return(0);
+}
+
+
+int
+getsec(int fd, uchar *place, vlong lba, int nsec)
+{
+	return pread(fd, place, nsec * 512, lba * 512);
+}
+
+int
+putsec(int fd, uchar *place, vlong lba, int nsec)
+{
+	return pwrite(fd, place, nsec * 512, lba * 512);
+}
+
+static int pktn = 0;
+static uchar *pktbp = NULL;
+
+int
+getpkt(int fd, uchar *buf, int sz)
+{
+	register struct bpf_hdr *bh;
+	register int pktlen, retlen;
+	
+	if (pktn <= 0) { 
+		if ((pktn = read(fd, pktbuf, pktbufsz)) < 0) {
+			perror("read");
+			exit(1);
+		}
+		pktbp = pktbuf;
+	}
+
+	bh = (struct bpf_hdr *) pktbp;
+	retlen = (int) bh->bh_caplen;
+	/* This memcpy() is currently needed */ 
+	memcpy(buf, (void *)(pktbp + bh->bh_hdrlen),
+		retlen > sz ? sz : retlen);
+	pktlen = bh->bh_hdrlen + bh->bh_caplen; 
+	
+	pktbp = pktbp + BPF_WORDALIGN(pktlen);
+	pktn  -= (int) BPF_WORDALIGN(pktlen);
+
+	return retlen; 
+}
+
+int
+putpkt(int fd, uchar *buf, int sz)
+{
+	return write(fd, buf, sz);
+}
+
+vlong
+getsize(int fd)
+{
+	vlong size;
+	struct stat s;
+	int n;
+	struct disklabel lab;
+
+	// Try getting disklabel from block dev
+	if ((n = ioctl(fd, DIOCGDINFO, lab)) != -1) {  
+		size = lab.d_secsize * lab.d_secperunit;
+	} else {
+		// must not be a block special dev
+		if (fstat(fd, &s) == -1) {
+			perror("getsize");
+			exit(1);
+		}
+		size = s.st_size;
+	}
+	printf("ioctl returned %d\n", n);
+	printf("%lld bytes\n", size);
+	return size;
+}

+ 12 - 0
linux.c

@@ -100,6 +100,18 @@ putsec(int fd, uchar *place, vlong lba, int nsec)
 	return write(fd, place, nsec * 512);
 	return write(fd, place, nsec * 512);
 }
 }
 
 
+int
+getpkt(int fd, uchar *buf, int sz)
+{
+	return read(fd, buf, sz);
+}
+
+int
+putpkt(int fd, uchar *buf, int sz)
+{
+	return write(fd, buf, sz);
+}
+
 vlong
 vlong
 getsize(int fd)
 getsize(int fd)
 {
 {

+ 21 - 3
makefile

@@ -1,12 +1,30 @@
 # makefile for vblade
 # makefile for vblade
 
 
-O=aoe.o linux.o ata.o
+# see README for others
+PLATFORM=linux
+
+O=aoe.o ${PLATFORM}.o ata.o
 CFLAGS += -Wall -g -O2
 CFLAGS += -Wall -g -O2
+CC = gcc
 
 
 vblade: $O
 vblade: $O
-	cc -o vblade $O
+	${CC} -o vblade $O
+
+aoe.o : aoe.c config.h dat.h fns.h makefile
+	${CC} ${CFLAGS} -c $<
+
+${PLATFORM}.o : ${PLATFORM}.c config.h dat.h fns.h makefile
+	${CC} ${CFLAGS} -c $<
+
+ata.o : ata.c config.h dat.h fns.h makefile
+	${CC} ${CFLAGS} -c $<
 
 
-$O: dat.h fns.h
+config.h : config/config.h.in makefile
+	@if ${CC} ${CFLAGS} config/u64.c > /dev/null 2>&1; then \
+	  sh -xc "cp config/config.h.in config.h"; \
+	else \
+	  sh -xc "sed 's!^//u64 !!' config/config.h.in > config.h"; \
+	fi
 
 
 clean :
 clean :
 	rm -f $O vblade
 	rm -f $O vblade

BIN
vblade


+ 1 - 1
vbladed

@@ -12,4 +12,4 @@ then
     exit 1
     exit 1
 fi
 fi
 
 
-sh -c "`dirname $0`/vblade - $* < /dev/null 2>&1 | logger -t vbladed" &
+sh -c "`dirname $0`/vblade $* < /dev/null 2>&1 | logger -t vbladed" &