MachCtl-SVN | 13 Dec 15:35
Favicon

machctl: r15 - sys

Author: vedge
Date: 2008-12-13 10:35:20 -0400 (Sat, 13 Dec 2008)
New Revision: 15

Modified:
   sys/patch-OpenBSD_4.0
Log:
remove new files from patch


Modified: sys/patch-OpenBSD_4.0
===================================================================
--- sys/patch-OpenBSD_4.0	2008-03-25 09:55:16 UTC (rev 14)
+++ sys/patch-OpenBSD_4.0	2008-12-13 14:35:20 UTC (rev 15)
 <at>  <at>  -60,2439 +60,6  <at>  <at> 
  
  # clonable devices
  pseudo-device	bpfilter 	# packet filter
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc.c sys/dev/cnc/cnc.c
---- sys.ORIG/dev/cnc/cnc.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc.c	Fri Jun  8 07:00:53 2007
- <at>  <at>  -0,0 +1,597  <at>  <at> 
-+/*	$OpenBSD$	*/
-+
-+/*
-+ * Copyright (c) 2007 Hypertriton, Inc. <http://www.hypertriton.com/>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+ * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-+ * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+/*
-+ * Real-time control interface for CNC machinery and robots.
-+ */
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/ioctl.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+#include <sys/pool.h>
-+#include <sys/conf.h>
-+#include <sys/lock.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include "cnc_devicevar.h"
-+#include "cnc_servovar.h"
-+#include "cnc_estopvar.h"
-+#include "cnc_spindlevar.h"
-+#include "cncvar.h"
-+
-+#define STEPMAX	(INT64_MAX-1)
-+#define STEPLEN 20336			/* 20336 units = 1 step */
-+#define MAXSTEPS (STEPMAX/STEPLEN)
-+
-+cnc_real_t cnc_Vmax = 2000.0;		/* maximum velocity (steps/sec) */
-+u_long cnc_timebase = 0;		/* delay loop calibration */
-+
-+const char *cnc_insn_names[] = {
-+	"MOVE",
-+	"SET_INTERP",
-+	"SPINDLE_DIR",
-+	"SPINDLE_SPEED",
-+	"SPINDLE_START",
-+	"SPINDLE_STOP",
-+	"ATC_PREPARE",
-+	"ATC_CHANGE",
-+	"LASER_ON",
-+	"LASER_OFF",
-+	"LASER_CURRENT",
-+	"PICKPLACE_REEL",
-+	"PICKPLACE_SUCTION",
-+	"PICKPLACE_RELEASE",
-+	"PREEMPT",
-+	"DWELL",
-+	"COOL_MIST",
-+	"COOL_FLOOD",
-+	"COOL_VORTEX"
-+};
-+
-+struct pool cnc_insnpl;
-+int cnc_opened;
-+TAILQ_HEAD(,cnc_insn) cnc_prog;
-+struct cnc_vector cnc_pos;
-+struct cnc_device *cnc_servos[CNC_NAXES];
-+struct cnc_device *cnc_spindles[CNC_MAX_SPINDLES];
-+struct cnc_device *cnc_estops[CNC_MAX_ESTOPS];
-+struct cnc_device *cnc_estop;
-+int cnc_nservos = 0;
-+int cnc_nspindles = 0;
-+int cnc_nestops = 0;
-+
-+void
-+cncattach(int num)
-+{
-+	int i;
-+
-+	if (num > 1)
-+		return;
-+
-+	printf("cnc: STEPLEN=%u, Vmax = %d steps/s\n",
-+	    (u_int)STEPLEN, (int)cnc_Vmax);
-+	cnc_opened = 0;
-+	pool_init(&cnc_insnpl, sizeof(struct cnc_insn), 0, 0, 0, "cncinsnpl",
-+	    NULL);
-+	pool_setlowat(&cnc_insnpl, 1024);
-+	TAILQ_INIT(&cnc_prog);
-+
-+	for (i = 0; i < CNC_NAXES; i++)
-+		cnc_pos.v[i] = 0;
-+}
-+
-+int
-+cncdetach(struct device *self, int flags)
-+{
-+	cnc_prog_reset();
-+	return (0);
-+}
-+
-+int
-+cncactivate(struct device *self, enum devact a)
-+{
-+	return (0);
-+}
-+
-+int
-+cncopen(dev_t dev, int flag, int mode, struct proc *p)
-+{
-+	if (cnc_opened) {
-+		return (EBUSY);
-+	}
-+	cnc_opened = 1;
-+	return (0);
-+}
-+
-+int
-+cncclose(dev_t dev, int flag, int mode, struct proc *p)
-+{
-+	cnc_prog_reset();
-+	cnc_opened = 0;
-+	return (0);
-+}
-+
-+struct cnc_device *
-+cnc_get_spindle(int id)
-+{
-+	if (id < 0 || id >= cnc_nspindles) {
-+		return (NULL);
-+	}
-+	return (cnc_spindles[id]);
-+}
-+
-+int
-+cncwrite(dev_t dev, struct uio *uio, int ioflag)
-+{
-+	const char *cause;
-+	struct cnc_insn insn, *iNew;
-+	u_int ip = 0;
-+	void *p;
-+
-+	while (uio->uio_resid > 0) {
-+		int rv;
-+
-+		rv = uiomove(&insn, sizeof(struct cnc_insn), uio);
-+		if (rv != 0) {
-+			printf("cncwrite: uiomove: %d\n", rv);
-+			return (EIO);
-+		}
-+		if (insn.i_type < 0 || insn.i_type >= CNC_LAST_INSN) {
-+			printf("cncwrite: bad insn %d\n", insn.i_type);
-+			return (ENODEV);
-+		}
-+		/*
-+		 * We do the best we can to validate the program
-+		 * before it is executed.
-+		 */
-+		switch (insn.i_type) {
-+		case CNC_MOVE:
-+			if (cnc_vec_distance(&cnc_pos, &insn.i_pos) == 0) {
-+				cause = "L=0";
-+				goto fail;
-+			}
-+			if (insn.i_Amax == 0) { cause = "Amax=0"; goto fail; }
-+			if (insn.i_Jmax == 0) { cause = "Jmax=0"; goto fail; }
-+			break;
-+		case CNC_SET_INTERP:
-+			if (insn.i_interp_mode < 0 ||
-+			    insn.i_interp_mode >= CNC_INTERP_LAST) {
-+				cause = "bad interpolation mode";
-+				goto fail;
-+			}
-+			break;
-+		case CNC_SPINDLE_DIR:
-+			if (cnc_get_spindle(insn.i_spindle_id) == NULL) {
-+				cause = "no such spindle";
-+				goto fail;
-+			}
-+			if (insn.i_spindle_dir != -1 &&
-+			    insn.i_spindle_dir != 1) {
-+				cause = "bad direction";
-+				goto fail;
-+			}
-+			break;
-+		case CNC_SPINDLE_SPEED:
-+			if ((p = cnc_get_spindle(insn.i_spindle_id)) == NULL) {
-+				cause = "no such spindle";
-+				goto fail;
-+			} else {
-+				struct spindle_softc *sc = p;
-+
-+				if (insn.i_spindle_speed > sc->sc_speed_max) {
-+					cause = "speed exceeds spindle limit";
-+					goto fail;
-+				}
-+			}
-+			break;
-+		case CNC_SPINDLE_START:
-+		case CNC_SPINDLE_STOP:
-+			if ((p = cnc_get_spindle(insn.i_spindle_id)) == NULL) {
-+				cause = "no such spindle";
-+				goto fail;
-+			}
-+			break;
-+		default:
-+			break;
-+		}
-+		if ((iNew = pool_get(&cnc_insnpl, 0)) == NULL) {
-+			cause = "out of memory for instruction";
-+			goto fail;
-+		}
-+		memcpy(iNew, &insn, sizeof(struct cnc_insn));
-+		TAILQ_INSERT_TAIL(&cnc_prog, iNew, prog);
-+		ip++;
-+	}
-+	printf("cnc: added %u insns to queue\n", ip);
-+	return (0);
-+fail:
-+	printf("%s[%d]: %s\n", cnc_insn_names[insn.i_type], ip, cause);
-+	return (EINVAL);
-+}
-+
-+void
-+cnc_prog_reset(void)
-+{
-+	struct cnc_insn *in;
-+	u_int ninsns = 0;
-+
-+	while ((in = TAILQ_FIRST(&cnc_prog)) != NULL) {
-+		TAILQ_REMOVE(&cnc_prog, in, prog);
-+		pool_put(&cnc_insnpl, in);
-+		ninsns++;
-+	}
-+/*	printf("cnc: deleted %u insns\n", ninsns); */
-+}
-+
-+int
-+cnc_prog_exec(void)
-+{
-+	struct cnc_insn *insn;
-+	u_int ninsns = 0;
-+	int s;
-+
-+	if (cnc_nservos != CNC_NAXES) {
-+		printf("cnc: nservos=%d, but CNC_NAXES=%d\n", cnc_nservos,
-+		    CNC_NAXES);
-+		return (EIO);
-+	}
-+
-+	printf("cnc: executing program\n");
-+
-+	s = splclock();
-+	TAILQ_FOREACH(insn, &cnc_prog, prog) {
-+		switch (insn->i_type) {
-+		case CNC_MOVE:
-+			if (cnc_move(insn) == -1) {
-+				goto fail;
-+			}
-+			break;
-+#if NSPINDLE > 0
-+		case CNC_SPINDLE_START:
-+			spindle_start(cnc_spindles[insn->i_spindle_id], insn);
-+			break;
-+		case CNC_SPINDLE_STOP:
-+			spindle_stop(cnc_spindles[insn->i_spindle_id], insn);
-+			break;
-+		case CNC_SPINDLE_SPEED:
-+			spindle_speed(cnc_spindles[insn->i_spindle_id], insn);
-+			break;
-+#endif
-+		default:
-+			break;
-+		}
-+		printf("insn %u: type=%d\n", ninsns, insn->i_type);
-+		ninsns++;
-+	}
-+	splx(s);
-+	return (0);
-+fail:
-+	splx(s);
-+	return (EIO);
-+}
-+
-+/*
-+ * Try to calibrate cnc_timebase to a value that will give us as
-+ * close as possible to 1 second. There is no portable way to do
-+ * this so we repeatedly benchmark results of a real delay loop
-+ * until the error is reduced to a minimum.
-+ *
-+ * This can take a while, but only needs to be run once on any
-+ * given machine.
-+ *
-+ * XXX the algorithm should be optimized based on the rate of change
-+ * in the results.
-+ */
-+u_long
-+cnc_calibrate_timebase(void)
-+{
-+	struct timeval tv1, tv2;
-+	long ds, du, d;
-+	u_long timebase = 10000000, i;
-+	int s, j;
-+
-+	s = splhigh();
-+	printf("cnc: calibrating timebase...");
-+	for (j = 0; j < 500; j++) {
-+		microtime(&tv1);
-+		for (i = 0; i < timebase; i++)
-+			;;
-+		microtime(&tv2);
-+		ds = tv2.tv_sec - tv1.tv_sec;
-+		du = tv2.tv_usec - tv1.tv_usec;
-+
-+		printf(" %ld", 1000000-du);
-+		if (ds < 0) {
-+			timebase += 1000000;
-+		} else if (ds > 0) {
-+			timebase -= 1000000;
-+		} else if (ds == 0 && du < 1000000) {
-+			d = 1000000 - du;
-+			timebase += d*4;
-+			if (d < 10) { break; }
-+		} else if (ds == 0 && du > 1000000) {
-+			d = du - 1000000;
-+			timebase -= d*4;
-+			if (d < 10) { break; }
-+		} else {
-+			break;
-+		}
-+	}
-+	splx(s);
-+	printf("\n");
-+	return (timebase);
-+}
-+
-+int
-+cncioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
-+{
-+	struct cnc_kinematics *kin;
-+	cnc_vec_t *pos;
-+	int i;
-+
-+	switch (cmd) {
-+	case CNC_EXECPROG:
-+		return (cnc_prog_exec());
-+	case CNC_RESETPROG:
-+		return (cnc_prog_exec());
-+	case CNC_GETPOS:
-+		pos = (cnc_vec_t *)data;
-+		for (i = 0; i < CNC_NAXES; i++) {
-+			pos->v[i] = cnc_pos.v[i];
-+		}
-+		return (0);
-+	case CNC_SETPOS:
-+		pos = (cnc_vec_t *)data;
-+		for (i = 0; i < CNC_NAXES; i++) {
-+			printf("cnc: axis %d: %lu -> %lu", i, cnc_pos.v[i],
-+			    pos->v[i]);
-+			cnc_pos.v[i] = pos->v[i];
-+		}
-+		return (0);
-+	case CNC_GETNSERVOS:
-+		*(int *)data = cnc_nservos;
-+		return (0);
-+	case CNC_GETNSPINDLES:
-+		*(int *)data = cnc_nspindles;
-+		return (0);
-+	case CNC_GETNESTOPS:
-+		*(int *)data = cnc_nestops;
-+		return (0);
-+	case CNC_GETKINLIMITS:
-+		kin = (struct cnc_kinematics *)data;
-+//		kin->k_Ts = (int)cnc_Ts;
-+		kin->k_Vmax = (int)cnc_Vmax;
-+		return (0);
-+	case CNC_SETKINLIMITS:
-+		kin = (struct cnc_kinematics *)data;
-+		if (kin->k_Ts < 0 || kin->k_Vmax < 0) {
-+			return (EINVAL);
-+		}
-+//		cnc_Ts = (cnc_real_t)kin->k_Ts;
-+		cnc_Vmax = (cnc_real_t)kin->k_Vmax;
-+		return (0);
-+	case CNC_GETTIMEBASE:
-+		*(u_long *)data = cnc_timebase;
-+		return (0);
-+	case CNC_SETTIMEBASE:
-+		cnc_timebase = *(u_long *)data;
-+		return (0);
-+	case CNC_CALTIMEBASE:
-+		*(u_long *)data = cnc_calibrate_timebase();
-+		return (0);
-+	default:
-+		break;
-+	}
-+	return (ENODEV);
-+}
-+
-+void
-+cnc_move_axis(enum cnc_axis axis, int dir)
-+{
-+	servo_step(cnc_servos[axis], dir);
-+	cnc_pos.v[axis] += dir;
-+}
-+
-+/* Check whether an e-stop device is active. */
-+int
-+cnc_estop_raised(void)
-+{
-+	int i;
-+
-+	for (i = 0; i < cnc_nestops; i++) {
-+		if (estop_get_state(cnc_estops[i])) {
-+			printf("%s: emergency stop\n",
-+			    cnc_estops[i]->cd_dev.dv_xname);
-+			return (1);
-+		}
-+	}
-+	return (0);
-+}
-+
-+/*
-+ * Coordinated movement of the n axes to a target position in n-dimensional
-+ * space at the specified feed rate.
-+ *
-+ * TODO Specialized applications could use another algorithm to provide a
-+ * more constant velocity through simultaneous deceleration and acceleration
-+ * of the axes, at the cost of contour errors proportional to Ts.
-+ */
-+int
-+cnc_move(struct cnc_insn *insn)
-+{
-+	struct cnc_quintic_profile qprof;
-+	cnc_real_t t;
-+#if CNC_NAXES == 3
-+	cnc_pos_t x1 = cnc_pos.v[CNC_X];
-+	cnc_pos_t y1 = cnc_pos.v[CNC_Y];
-+	cnc_pos_t z1 = cnc_pos.v[CNC_Z];
-+	cnc_pos_t x2 = insn->i_pos.v[CNC_X];
-+	cnc_pos_t y2 = insn->i_pos.v[CNC_Y];
-+	cnc_pos_t z2 = insn->i_pos.v[CNC_Z];
-+	cnc_pos_t dx, dy, dz;
-+	cnc_pos_t x, y, z;
-+	int xdir, ydir, zdir;
-+#endif
-+
-+#if CNC_NAXES == 3
-+	dx = abs(x2 - x1);
-+	dy = abs(y2 - y1);
-+	dz = abs(z2 - z1);
-+
-+	if (dx == 0 && dy == 0 && dz == 0)
-+		return (0);
-+
-+	xdir = (x2 > x1) ? 1 : -1;
-+	ydir = (y2 > y1) ? 1 : -1;
-+	zdir = (z2 > z1) ? 1 : -1;
-+
-+	printf("MOVE: Delta=%ld,%ld,%ld\n", dx, dy, dz);
-+	printf("MOVE: Dir=%d,%d,%d\n", xdir, ydir, zdir);
-+	printf("MOVE: F = %d st/s, Amax = %d st/s^2, Jmax = %d st/s^3\n",
-+	    insn->i_F, insn->i_Amax, insn->i_Jmax);
-+
-+	if (dx >= dy && dx >= dz) {
-+		dy = dy*STEPLEN/dx;
-+		dz = dz*STEPLEN/dx;
-+		if (cnc_quintic_init(&qprof, insn, (cnc_real_t)dx) == -1) {
-+			goto fail;
-+		}
-+		for (x = 0, t = 0.0;
-+		     x < dx && t < MAXSTEPS;
-+		     x++, t+=1.0) {
-+			y = (dy*ydir*t)/STEPLEN;
-+			z = (dz*zdir*t)/STEPLEN;
-+			if (cnc_estop_raised()) {
-+				goto fail;
-+			}
-+			cnc_move_axis(CNC_X, xdir);
-+			if (y1+y != cnc_pos.v[CNC_Y]) {
-+				cnc_move_axis(CNC_Y, y);
-+				cnc_pos.v[CNC_Y] = y1+y;
-+			}
-+			if (z1+z != cnc_pos.v[CNC_Z]) {
-+				cnc_move_axis(CNC_Z, z);
-+				cnc_pos.v[CNC_Z] = z1+z;
-+			}
-+			cnc_move_delay(&qprof, t, (cnc_real_t)dx);
-+		}
-+	} else if (dy >= dx && dy >= dz) {
-+		dx = dx*STEPLEN/dy;
-+		dz = dz*STEPLEN/dy;
-+		if (cnc_quintic_init(&qprof, insn, (cnc_real_t)dy) == -1) {
-+			goto fail;
-+		}
-+		for (y = 0, t = 0.0;
-+		     y < dy && t < MAXSTEPS;
-+		     y++, t+=1.0) {
-+			x = (dx*xdir*t)/STEPLEN;
-+			z = (dz*zdir*t)/STEPLEN;
-+			if (cnc_estop_raised()) {
-+				goto fail;
-+			}
-+			cnc_move_axis(CNC_Y, ydir);
-+			if (x1+x != cnc_pos.v[CNC_X]) {
-+				cnc_move_axis(CNC_X, x);
-+				cnc_pos.v[CNC_X] = x1+x;
-+			}
-+			if (z1+z != cnc_pos.v[CNC_Z]) {
-+				cnc_move_axis(CNC_Z, z);
-+				cnc_pos.v[CNC_Z] = z1+z;
-+			}
-+			cnc_move_delay(&qprof, t, (cnc_real_t)dy);
-+		}
-+	} else if (dz >= dx && dz >= dy) {
-+		dx = dx*STEPLEN/dz;
-+		dy = dy*STEPLEN/dz;
-+		if (cnc_quintic_init(&qprof, insn, (cnc_real_t)dz) == -1) {
-+			goto fail;
-+		}
-+		for (z = 0, t = 0.0;
-+		     z < dz && t < MAXSTEPS;
-+		     z++, t+=1.0) {
-+			x = (dx*xdir*t)/STEPLEN;
-+			y = (dy*ydir*t)/STEPLEN;
-+			if (cnc_estop_raised()) {
-+				goto fail;
-+			}
-+			cnc_move_axis(CNC_Z, zdir);
-+			if (x1+x != cnc_pos.v[CNC_X]) {
-+				cnc_move_axis(CNC_X, x);
-+				cnc_pos.v[CNC_X] = x1+x;
-+			}
-+			if (y1+y != cnc_pos.v[CNC_Y]) {
-+				cnc_move_axis(CNC_Y, y);
-+				cnc_pos.v[CNC_Y] = y1+y;
-+			}
-+			cnc_move_delay(&qprof, t, (cnc_real_t)dz);
-+		}
-+	} else {
-+		printf("MOVE: Bad case\n");
-+		goto fail;
-+	}
-+#endif
-+	return (0);
-+fail:
-+	printf("MOVE: Aborted instruction\n");
-+	return (-1);
-+}
-+
-+/*
-+ * Enter a precisely-calculated loop that will give us the proper delay
-+ * between two steps.
-+ */
-+void
-+cnc_move_delay(const struct cnc_quintic_profile *q, cnc_real_t t, cnc_real_t L)
-+{
-+	cnc_real_t v;
-+	u_long delay;
-+	u_long j;
-+
-+	v = cnc_quintic_step(q, t*(q->Ta + q->To)/L)*q->F/(q->v0+q->v1+q->v2) +
-+	    q->v0;
-+	delay = (u_long)(cnc_timebase/v);
-+	if (delay > cnc_timebase) {
-+		delay = cnc_timebase;
-+	}
-+#if 1
-+	for (j = 0; j < delay; j++)
-+		;;
-+#else
-+	printf("[%lu] %s steps/sec (delay=%lu)\n", (u_long)t, cnc_fmt_real(v),
-+	    delay);
-+#endif
-+}
-+
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_cbrt.c sys/dev/cnc/cnc_cbrt.c
---- sys.ORIG/dev/cnc/cnc_cbrt.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_cbrt.c	Wed May 30 01:06:05 2007
- <at>  <at>  -0,0 +1,96  <at>  <at> 
-+/*  <at> (#)s_cbrt.c 5.1 93/09/24 */
-+/*
-+ * ====================================================
-+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-+ *
-+ * Developed at SunPro, a Sun Microsystems, Inc. business.
-+ * Permission to use, copy, modify, and distribute this
-+ * software is freely granted, provided that this notice 
-+ * is preserved.
-+ * ====================================================
-+ */
-+
-+#if defined(LIBM_SCCS) && !defined(lint)
-+static char rcsid[] = "$NetBSD: s_cbrt.c,v 1.8 1995/05/10 20:46:49 jtc Exp $";
-+#endif
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/ioctl.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include "cnc_devicevar.h"
-+#include "cncvar.h"
-+#include "math_private.h"
-+
-+/* cbrt(x)
-+ * Return cube root of x
-+ */
-+static const u_int32_t
-+	B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
-+	B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
-+
-+static const double
-+C =  5.42857142857142815906e-01, /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
-+D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
-+E =  1.41428571428571436819e+00, /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
-+F =  1.60714285714285720630e+00, /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
-+G =  3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
-+
-+double
-+cnc_cbrt(double x) 
-+{
-+	int32_t	hx;
-+	double r,s,t=0.0,w;
-+	u_int32_t sign;
-+	u_int32_t high,low;
-+
-+	GET_HIGH_WORD(hx,x);
-+	sign=hx&0x80000000; 		/* sign= sign(x) */
-+	hx  ^=sign;
-+	if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
-+	GET_LOW_WORD(low,x);
-+	if((hx|low)==0) 
-+	    return(x);		/* cbrt(0) is itself */
-+
-+	SET_HIGH_WORD(x,hx);	/* x <- |x| */
-+    /* rough cbrt to 5 bits */
-+	if(hx<0x00100000) 		/* subnormal number */
-+	  {SET_HIGH_WORD(t,0x43500000);	/* set t= 2**54 */
-+	   t*=x; GET_HIGH_WORD(high,t); SET_HIGH_WORD(t,high/3+B2);
-+	  }
-+	else
-+	  SET_HIGH_WORD(t,hx/3+B1);
-+
-+
-+    /* new cbrt to 23 bits, may be implemented in single precision */
-+	r=t*t/x;
-+	s=C+r*t;
-+	t*=G+F/(s+E+D/s);	
-+
-+    /* chopped to 20 bits and make it larger than cbrt(x) */ 
-+	GET_HIGH_WORD(high,t);
-+	INSERT_WORDS(t,high+0x00000001,0);
-+
-+
-+    /* one step newton iteration to 53 bits with error less than 0.667 ulps */
-+	s=t*t;		/* t*t is exact */
-+	r=x/s;
-+	w=t+t;
-+	r=(r-t)/(w+r);	/* r-s is exact */
-+	t=t+t*r;
-+
-+    /* retore the sign bit */
-+	GET_HIGH_WORD(high,t);
-+	SET_HIGH_WORD(t,high|sign);
-+	return(t);
-+}
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_device.c sys/dev/cnc/cnc_device.c
---- sys.ORIG/dev/cnc/cnc_device.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_device.c	Thu Jun  7 03:12:27 2007
- <at>  <at>  -0,0 +1,113  <at>  <at> 
-+/*	$OpenBSD$	*/
-+
-+/*
-+ * Copyright (c) 2007 Hypertriton, Inc. <http://www.hypertriton.com/>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+ * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-+ * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+/*
-+ * Generic CNC device code.
-+ */
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/ioctl.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+#include <sys/pool.h>
-+#include <sys/conf.h>
-+#include <sys/lock.h>
-+#include <sys/kthread.h>
-+
-+#include <sys/cnc.h>
-+
-+#include "cnc_devicevar.h"
-+#include "cncvar.h"
-+
-+struct cnc_deviceq cnc_devices;
-+int cnc_initialized = 0;
-+
-+int
-+cnc_device_attach(void *p, enum cnc_device_type type)
-+{
-+	struct cnc_device *cd = p;
-+
-+	if (!cnc_initialized) {
-+		TAILQ_INIT(&cnc_devices);
-+		cnc_initialized = 1;
-+	}
-+	cd->cd_type = type;
-+	cd->cd_flags = 0;
-+	TAILQ_INSERT_TAIL(&cnc_devices, cd, devices);
-+
-+	switch (type) {
-+	case CNC_DEVICE_SERVO:
-+		if ((cnc_nservos+1) <= CNC_NAXES) {
-+			printf(": axis %d\n", cnc_nservos);
-+			cnc_servos[cnc_nservos++] = cd;
-+		} else {
-+			printf(": ignored (bump CNC_NAXES)\n");
-+		}
-+		break;
-+	case CNC_DEVICE_SPINDLE:
-+		if ((cnc_nspindles+1) <= CNC_MAX_SPINDLES) {
-+			printf(": spindle %d\n", cnc_nspindles);
-+			cnc_spindles[cnc_nspindles++] = cd;
-+		} else {
-+			printf(": ignored (bump CNC_MAX_SPINDLES)\n");
-+		}
-+		break;
-+	case CNC_DEVICE_ESTOP:
-+		if ((cnc_nestops+1) <= CNC_MAX_ESTOPS) {
-+			printf(": estop %d\n", cnc_nestops);
-+			cnc_estops[cnc_nestops++] = cd;
-+		} else {
-+			printf(": ignored (bump CNC_MAX_ESTOPS)\n");
-+		}
-+		break;
-+	default:
-+		printf(": unimplemented\n");
-+		break;
-+	}
-+	printf("%s", cd->cd_dev.dv_xname);
-+	return (0);
-+}
-+
-+int
-+cnc_device_detach(void *p)
-+{
-+	struct cnc_device *cd = p;
-+
-+	TAILQ_REMOVE(&cnc_devices, cd, devices);
-+	return (0);
-+}
-+
-+int
-+cnc_device_activate(void *p)
-+{
-+	return (0);
-+}
-+
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_devicevar.h sys/dev/cnc/cnc_devicevar.h
---- sys.ORIG/dev/cnc/cnc_devicevar.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_devicevar.h	Thu Jun  7 03:07:52 2007
- <at>  <at>  -0,0 +1,26  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*	Public domain	*/
-+
-+enum cnc_device_type {
-+	CNC_DEVICE_ESTOP,		/* Emergency stop device */
-+	CNC_DEVICE_SERVO,		/* Servo motor controller */
-+	CNC_DEVICE_SPINDLE,		/* Machine spindle controller */
-+	CNC_DEVICE_ATC,			/* Automatic tool changer */
-+	CNC_DEVICE_LASER,		/* Laser power supply controller */
-+	CNC_DEVICE_PICKPLACE		/* Pick and place controller */
-+};
-+
-+struct cnc_device {
-+	struct device cd_dev;
-+	enum cnc_device_type cd_type;
-+	int cd_flags;
-+	TAILQ_ENTRY(cnc_device) devices;
-+};
-+
-+TAILQ_HEAD(cnc_deviceq,cnc_device);
-+extern struct cnc_deviceq cnc_devices;
-+
-+int cnc_device_attach(void *, enum cnc_device_type);
-+int cnc_device_detach(void *);
-+int cnc_device_activate(void *);
-+
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_estop.c sys/dev/cnc/cnc_estop.c
---- sys.ORIG/dev/cnc/cnc_estop.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_estop.c	Fri Jun  8 01:40:04 2007
- <at>  <at>  -0,0 +1,130  <at>  <at> 
-+/*	$OpenBSD$	*/
-+
-+/*
-+ * Copyright (c) 2007 Hypertriton, Inc. <http://www.hypertriton.com/>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+ * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-+ * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+/*
-+ * Driver for emergency stop button.
-+ */
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/ioctl.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+#include <sys/pool.h>
-+#include <sys/conf.h>
-+#include <sys/lock.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include <dev/cnc/cnc_devicevar.h>
-+#include <dev/cnc/cncvar.h>
-+#include <dev/cnc/cnc_estopvar.h>
-+
-+int	estop_match(struct device *, void *, void *);
-+void	estop_attach(struct device *, struct device *, void *);
-+int	estop_detach(struct device *, int);
-+int	estop_activate(struct device *, enum devact);
-+void	estop_abort_all(void);
-+
-+struct cfattach estop_ca = {
-+	sizeof(struct estop_softc),
-+	estop_match,
-+	estop_attach,
-+	estop_detach,
-+	estop_activate
-+};
-+
-+struct cfdriver estop_cd = {
-+	NULL, "estop", DV_DULL
-+};
-+
-+int
-+estop_match(struct device *parent, void *match, void *aux)
-+{
-+	struct cfdata *cf = match;
-+
-+	return (strcmp(cf->cf_driver->cd_name, "estop") == 0);
-+}
-+
-+void
-+estop_attach(struct device *parent, struct device *self, void *aux)
-+{
-+	struct estop_softc *sc = (struct estop_softc *)self;
-+	struct gpio_attach_args *ga = aux;
-+	int caps, ctl;
-+	
-+	sc->sc_flags = 0;
-+
-+	if (gpio_npins(ga->ga_mask) != ESTOP_NPINS) {
-+		printf(": invalid pin mask\n");
-+		return;
-+	}
-+	sc->sc_gpio = ga->ga_gpio;
-+	sc->sc_map.pm_map = sc->__map;
-+	if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
-+	    &sc->sc_map)) {
-+		printf(": can't map pins\n");
-+		return;
-+	}
-+	
-+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, ESTOP_PIN);
-+	if (!(caps & GPIO_PIN_INPUT)) {
-+		printf(": ESTOP pin is unable to read input\n");
-+		gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
-+		return;
-+	}
-+	printf(": ESTOP[%d]\n", sc->sc_map.pm_map[ESTOP_PIN]);
-+	ctl = GPIO_PIN_INPUT;
-+	if (caps & GPIO_PIN_PUSHPULL) { ctl |= GPIO_PIN_PUSHPULL; }
-+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, ESTOP_PIN, ctl);
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, ESTOP_PIN, GPIO_PIN_LOW);
-+}
-+
-+int
-+estop_detach(struct device *self, int flags)
-+{
-+	return (0);
-+}
-+
-+int
-+estop_activate(struct device *self, enum devact act)
-+{
-+	return (0);
-+}
-+
-+int
-+estop_get_state(void *p)
-+{
-+	struct estop_softc *sc = p;
-+	return (gpio_pin_read(sc->sc_gpio, &sc->sc_map, ESTOP_PIN));
-+}
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_estopvar.h sys/dev/cnc/cnc_estopvar.h
---- sys.ORIG/dev/cnc/cnc_estopvar.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_estopvar.h	Fri Jun  8 01:39:48 2007
- <at>  <at>  -0,0 +1,16  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*	Public domain	*/
-+
-+#define ESTOP_NPINS	1
-+#define ESTOP_PIN	0
-+
-+struct estop_softc {
-+	struct cnc_device sc_cdev;
-+
-+	int sc_flags;
-+	void *sc_gpio;
-+	struct gpio_pinmap sc_map;
-+	int __map[ESTOP_NPINS];
-+};
-+
-+int estop_get_state(void *);
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_log10.S sys/dev/cnc/cnc_log10.S
---- sys.ORIG/dev/cnc/cnc_log10.S	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_log10.S	Wed May 30 02:07:00 2007
- <at>  <at>  -0,0 +1,13  <at>  <at> 
-+/*	$OpenBSD: e_log10.S,v 1.2 2005/08/02 11:17:31 espie Exp $ */
-+/*
-+ * Written by J.T. Conklin <jtc-S783fYmB3Ccdnm+yROfE0A <at> public.gmane.org>.
-+ * Public domain.
-+ */
-+
-+#include <machine/asm.h>
-+
-+ENTRY(cnc_log10)
-+	fldlg2
-+	fldl	4(%esp)
-+	fyl2x
-+	ret
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_math.c sys/dev/cnc/cnc_math.c
---- sys.ORIG/dev/cnc/cnc_math.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_math.c	Wed May 30 09:19:43 2007
- <at>  <at>  -0,0 +1,96  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*	Public domain	*/
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/ioctl.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include "cnc_devicevar.h"
-+#include "cncvar.h"
-+
-+void
-+cnc_vec_init(cnc_vec_t v)
-+{
-+	int i;
-+
-+	for (i = 0; i < CNC_NAXES; i++)
-+		v.v[i] = 0;
-+}
-+
-+/* Return (v1-v2) in vDst. */
-+void
-+cnc_vec_sub(cnc_vec_t *vDst, const cnc_vec_t *v1, const cnc_vec_t *v2)
-+{
-+	int i;
-+
-+	for (i = 0; i < CNC_NAXES; i++)
-+		vDst->v[i] = v1->v[i] - v2->v[i];
-+}
-+
-+/* Return (v1+v2) in vDst. */
-+void
-+cnc_vec_add(cnc_vec_t *vDst, const cnc_vec_t *v1, const cnc_vec_t *v2)
-+{
-+	int i;
-+
-+	for (i = 0; i < CNC_NAXES; i++)
-+		vDst->v[i] = v1->v[i] + v2->v[i];
-+}
-+
-+/* Return real dot product of v1 and v2. */
-+cnc_real_t
-+cnc_vec_dotprod(cnc_vec_t *vDst, const cnc_vec_t *v1, const cnc_vec_t *v2)
-+{
-+	cnc_real_t dot = 0.0;
-+	int i;
-+
-+	for (i = 0; i < CNC_NAXES; i++) {
-+		dot += ((cnc_real_t)v1->v[i])*((cnc_real_t)v2->v[i]);
-+	}
-+	return (dot);
-+}
-+
-+/* Return real length of vector v. */
-+cnc_real_t
-+cnc_vec_length(const cnc_vec_t *v)
-+{
-+	cnc_real_t len_2 = 0.0;
-+	int i;
-+
-+	for (i = 0; i < CNC_NAXES; i++) {
-+		len_2 += ((cnc_real_t)v->v[i])*((cnc_real_t)v->v[i]);
-+	}
-+	return (cnc_sqrt(len_2));
-+}
-+
-+/* Return real distance between vectors v1 and v2. */
-+cnc_real_t
-+cnc_vec_distance(const cnc_vec_t *v1, const cnc_vec_t *v2)
-+{
-+	cnc_vec_t vd;
-+
-+	cnc_vec_sub(&vd, v2, v1);
-+	return (cnc_vec_length(&vd));
-+}
-+
-+char *
-+cnc_fmt_real(cnc_real_t v)
-+{
-+	static char s[64];
-+	double fpart;
-+	double ipart;
-+
-+	fpart = cnc_modf(v, &ipart);
-+	snprintf(s, sizeof(s), "%ld.%ld", (long)ipart, (long)(fpart*10000.0));
-+	return (s);
-+}
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_math.h sys/dev/cnc/cnc_math.h
---- sys.ORIG/dev/cnc/cnc_math.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_math.h	Wed May 30 08:50:13 2007
- <at>  <at>  -0,0 +1,21  <at>  <at> 
-+/*	$OpenBSD$	*/
-+
-+typedef float cnc_real_t;
-+
-+#define	CNC_PI		3.14159265358979323846	/* pi */
-+#define	CNC_PI_2	1.57079632679489661923	/* pi/2 */
-+#define CNC_MSECS(s)	((u_long)(s*1e3))
-+
-+double cnc_sin(double);
-+double cnc_sqrt(double);
-+double cnc_cbrt(double);
-+double cnc_log10(double);
-+double cnc_modf(double, double *);
-+char *cnc_fmt_real(cnc_real_t);
-+
-+void cnc_vec_init(cnc_vec_t);
-+void cnc_vec_sub(cnc_vec_t *, const cnc_vec_t *, const cnc_vec_t *);
-+void cnc_vec_add(cnc_vec_t *, const cnc_vec_t *, const cnc_vec_t *);
-+cnc_real_t cnc_vec_dotprod(cnc_vec_t *, const cnc_vec_t *, const cnc_vec_t *);
-+cnc_real_t cnc_vec_length(const cnc_vec_t *);
-+cnc_real_t cnc_vec_distance(const cnc_vec_t *, const cnc_vec_t *);
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_modf.c sys/dev/cnc/cnc_modf.c
---- sys.ORIG/dev/cnc/cnc_modf.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_modf.c	Wed May 30 06:45:59 2007
- <at>  <at>  -0,0 +1,90  <at>  <at> 
-+/*  <at> (#)s_modf.c 5.1 93/09/24 */
-+/*
-+ * ====================================================
-+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-+ *
-+ * Developed at SunPro, a Sun Microsystems, Inc. business.
-+ * Permission to use, copy, modify, and distribute this
-+ * software is freely granted, provided that this notice 
-+ * is preserved.
-+ * ====================================================
-+ */
-+
-+#if defined(LIBM_SCCS) && !defined(lint)
-+static char rcsid[] = "$NetBSD: s_modf.c,v 1.8 1995/05/10 20:47:55 jtc Exp $";
-+#endif
-+
-+/*
-+ * modf(double x, double *iptr) 
-+ * return fraction part of x, and return x's integral part in *iptr.
-+ * Method:
-+ *	Bit twiddling.
-+ *
-+ * Exception:
-+ *	No exception.
-+ */
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/ioctl.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include "cnc_devicevar.h"
-+#include "cncvar.h"
-+#include "math_private.h"
-+
-+static const double one = 1.0;
-+
-+double
-+cnc_modf(double x, double *iptr)
-+{
-+	int32_t i0,i1,j0;
-+	u_int32_t i;
-+	EXTRACT_WORDS(i0,i1,x);
-+	j0 = ((i0>>20)&0x7ff)-0x3ff;	/* exponent of x */
-+	if(j0<20) {			/* integer part in high x */
-+	    if(j0<0) {			/* |x|<1 */
-+	        INSERT_WORDS(*iptr,i0&0x80000000,0);	/* *iptr = +-0 */
-+		return x;
-+	    } else {
-+		i = (0x000fffff)>>j0;
-+		if(((i0&i)|i1)==0) {		/* x is integral */
-+		    u_int32_t high;
-+		    *iptr = x;
-+		    GET_HIGH_WORD(high,x);
-+		    INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
-+		    return x;
-+		} else {
-+		    INSERT_WORDS(*iptr,i0&(~i),0);
-+		    return x - *iptr;
-+		}
-+	    }
-+	} else if (j0>51) {		/* no fraction part */
-+	    u_int32_t high;
-+	    *iptr = x*one;
-+	    GET_HIGH_WORD(high,x);
-+	    INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
-+	    return x;
-+	} else {			/* fraction part in low x */
-+	    i = ((u_int32_t)(0xffffffff))>>(j0-20);
-+	    if((i1&i)==0) { 		/* x is integral */
-+	        u_int32_t high;
-+		*iptr = x;
-+		GET_HIGH_WORD(high,x);
-+		INSERT_WORDS(x,high&0x80000000,0);	/* return +-0 */
-+		return x;
-+	    } else {
-+	        INSERT_WORDS(*iptr,i0,i1&(~i));
-+		return x - *iptr;
-+	    }
-+	}
-+}
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_quintic.c sys/dev/cnc/cnc_quintic.c
---- sys.ORIG/dev/cnc/cnc_quintic.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_quintic.c	Fri Jun  8 06:58:07 2007
- <at>  <at>  -0,0 +1,167  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*
-+ * Copyright (c) 2007 Hypertriton, Inc. <http://www.hypertriton.com/>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+ * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-+ * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+/*
-+ * Quintic velocity profile generation.
-+ */
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/ioctl.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include "cnc_devicevar.h"
-+#include "cncvar.h"
-+
-+/*
-+ * Initialize constants to values that will yield an optimal time-energy
-+ * velocity profile under acceleration and jerk constraints.
-+ */
-+int
-+cnc_quintic_init(struct cnc_quintic_profile *q, const struct cnc_insn *insn,
-+    cnc_real_t L)
-+{
-+	cnc_real_t F = ((cnc_real_t)insn->i_F);
-+	cnc_real_t Amax = ((cnc_real_t)insn->i_Amax);
-+	cnc_real_t Jmax = ((cnc_real_t)insn->i_Jmax);
-+	cnc_real_t k;
-+
-+	q->F = F;
-+
-+//	if (F >= CNC_PI_2*((Amax*Amax)/Jmax) ) {
-+		/*
-+		 * Feedrate F is achievable by using maximum acceleration
-+		 * and maximum jerk.
-+		 */
-+		if (L >= ( (L*L)/Amax + CNC_PI_2*((Amax*F)/Jmax) )){
-+			/* Feedrate F is achievable at Amax acceleration. */
-+			printf("case 1.1\n");
-+			q->Ts = CNC_PI_2*(Amax/Jmax);
-+			q->Ta = (F/Amax) + q->Ts;
-+			q->To = L/F;
-+		} else if (L <  ( (F*F)/Amax + CNC_PI_2*((Amax*F)/Jmax) ) &&
-+	      		   L >= ( (CNC_PI*CNC_PI)/2.0) * (Amax*Amax*Amax) /
-+			                                     (Jmax*Jmax) ) {
-+			/* Feedrate F is unachievable, Amax is achievable. */
-+			printf("case 1.2\n");
-+			q->Ts = CNC_PI_2*(Amax/Jmax);
-+			q->Ta = ( (-CNC_PI*(Amax*Amax) +
-+			        cnc_sqrt((CNC_PI*CNC_PI)*(Amax*Amax*Amax*Amax) +
-+			                 16.0*Amax*(Jmax*Jmax)*L) ) /
-+			      (4.0*Jmax*Amax) ) + q->Ts;
-+			q->To = q->Ta;
-+		} else if (L <= ( ((CNC_PI*CNC_PI)/2.0)*(Amax*Amax*Amax) /
-+		                                            (Jmax*Jmax) )) {
-+			/* Neither F nor Amax are achievable. */
-+			printf("case 1.3\n");
-+			q->Ts = cnc_cbrt( (CNC_PI*L)/(4.0*Jmax) );
-+			q->Ta = 2.0*q->Ts;
-+			q->To = q->Ta;
-+//		} else {
-+//			printf("MOVE: Illegal parameters (1)\n");
-+//			return (-1);
-+		}
-+//	} else if (F < CNC_PI_2*((Amax*Amax)/Jmax) ) {
-+		/*
-+		 * Feedrate F is achievable without using maximum
-+		 * acceleration.
-+		 */
-+		if (L >= cnc_sqrt( (2.0*CNC_PI*(F*F*F))/Jmax ) ) {
-+			/* F is achievable, Amax is unachievable. */
-+			printf("case 2.1\n");
-+			q->Ts = cnc_sqrt( (CNC_PI*F)/(2.0*Jmax) );
-+			q->Ta = 2.0*q->Ts;
-+			q->To = L/F;
-+		} else if (L < cnc_sqrt( (2.0*CNC_PI*F*F*F)/Jmax )) {
-+			/* Neither F nor Amax are achievable. */
-+			printf("case 2.2\n");
-+			q->Ts = cnc_cbrt( (CNC_PI*L)/(4.0*Jmax) );
-+			q->Ta = 2.0*q->Ts;
-+			q->To = q->Ta;
-+		} else {
-+			printf("MOVE: Illegal parameters (2)\n");
-+			return (-1);
-+		}
-+//	}
-+
-+	k = CNC_PI/(2.0*q->Ts);
-+	q->Aref = L/(q->Ta - q->Ts) * q->To;
-+	q->v0 = ((cnc_real_t)insn->i_v0);
-+	q->v1 = (q->Aref/2.0) * (q->Ts - cnc_sin(2.0*k*q->Ts)/(2.0*k) );
-+	q->v2 = q->Aref*(q->Ta - 2.0*q->Ts) + q->v1;
-+
-+	printf("MOVE: ");
-+	printf("F=%s ", cnc_fmt_real(F));
-+	printf("v1=%s ", cnc_fmt_real(q->v1));
-+	printf("v2=%s ", cnc_fmt_real(q->v2));
-+	printf("v3=%s ", cnc_fmt_real(q->v1+q->v2));
-+	printf("Amax=%s ", cnc_fmt_real(Amax));
-+	printf("Jmax=%s ", cnc_fmt_real(Jmax));
-+	printf("Ta=%s ", cnc_fmt_real(q->Ta));
-+	printf("Ts=%s ", cnc_fmt_real(q->Ts));
-+	printf("To=%s\n", cnc_fmt_real(q->To));
-+	return (0);
-+}
-+
-+cnc_real_t
-+cnc_quintic_step(const struct cnc_quintic_profile *q, cnc_real_t t)
-+{
-+	cnc_real_t t2, t5, t6;
-+	cnc_real_t k = CNC_PI/(2.0*q->Ts);
-+	
-+	t2 = q->Ta - q->Ts;
-+	t5 = q->To + q->Ts;
-+	t6 = q->To + q->Ta - q->Ts;
-+
-+	if (t <= q->Ts) {
-+		return (q->Aref/2.0)*( t - cnc_sin(2.0*k*t)/(2.0*k) );
-+	} else if (t <= (q->Ta - q->Ts)) {
-+		return q->Aref*(t - q->Ts) + q->v1;
-+	} else if (t <= q->Ta) {
-+		return (q->Aref/2.0)*( (t-t2) + cnc_sin(2.0*k*(t-t2))/(2.0*k) )
-+		        + q->v2;
-+	} else if (t <= q->To) {
-+		return (q->v1 + q->v2);
-+	} else if (t <= t5) {
-+		return -(q->Aref/2.0) *
-+		         ( (t - q->To) - cnc_sin(2.0*k*(t - q->To))/(2.0*k) )
-+		       + (q->v1 + q->v2);
-+	} else if (t <= t6) {
-+		return -q->Aref*(t-t5) + q->v2;
-+	} else {
-+		return -(q->Aref/2.0)*( (t-t6) + cnc_sin(2.0*k*(t-t6))/(2.0*k) )
-+		        + q->v1;
-+	}
-+}
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_quintic.h sys/dev/cnc/cnc_quintic.h
---- sys.ORIG/dev/cnc/cnc_quintic.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_quintic.h	Tue Jun  5 23:48:28 2007
- <at>  <at>  -0,0 +1,16  <at>  <at> 
-+/*	Public domain	*/
-+
-+struct cnc_quintic_profile {
-+	cnc_real_t F;			/* User-given feed rate */
-+	cnc_real_t v0;			/* User-given min velocity */
-+	cnc_real_t Aref;		/* Effective acceleration */
-+	cnc_real_t Ts;			/* Domain of third-order sine */
-+	cnc_real_t Ta;			/* Total acceleration time */
-+	cnc_real_t To;			/* Total time before deceleration */
-+	cnc_real_t v1;			/* Velocity at Ts */
-+	cnc_real_t v2;			/* Velocity at Ta-Ts */
-+};
-+
-+int cnc_quintic_init(struct cnc_quintic_profile *, const struct cnc_insn *,
-+	             cnc_real_t);
-+cnc_real_t cnc_quintic_step(const struct cnc_quintic_profile *, cnc_real_t);
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_servo.c sys/dev/cnc/cnc_servo.c
---- sys.ORIG/dev/cnc/cnc_servo.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_servo.c	Wed Jun  6 23:45:33 2007
- <at>  <at>  -0,0 +1,227  <at>  <at> 
-+/*	$OpenBSD$	*/
-+
-+/*
-+ * Copyright (c) 2007 Hypertriton, Inc. <http://www.hypertriton.com/>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+ * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-+ * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+/*
-+ * Stepper/servo motor control with step/direction signal.
-+ */
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+#include <sys/pool.h>
-+#include <sys/conf.h>
-+#include <sys/lock.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include <dev/cnc/cnc_devicevar.h>
-+#include <dev/cnc/cncvar.h>
-+#include <dev/cnc/cnc_servovar.h>
-+
-+int	servo_match(struct device *, void *, void *);
-+void	servo_attach(struct device *, struct device *, void *);
-+int	servo_detach(struct device *, int);
-+int	servo_activate(struct device *, enum devact);
-+
-+struct cfattach servo_ca = {
-+	sizeof(struct servo_softc),
-+	servo_match,
-+	servo_attach,
-+	servo_detach,
-+	servo_activate
-+};
-+
-+struct cfdriver servo_cd = {
-+	NULL, "servo", DV_DULL
-+};
-+
-+int
-+servo_match(struct device *parent, void *match, void *aux)
-+{
-+	struct cfdata *cf = match;
-+
-+	return (strcmp(cf->cf_driver->cd_name, "servo") == 0);
-+}
-+
-+void
-+servo_attach(struct device *parent, struct device *self, void *aux)
-+{
-+	struct servo_softc *sc = (struct servo_softc *)self;
-+	struct gpio_attach_args *ga = aux;
-+	int caps, ctl;
-+
-+	/* Generic CNC device initialization. */
-+	if (cnc_device_attach(sc, CNC_DEVICE_SERVO) == -1)
-+		goto fail;
-+
-+	/* Check that we have enough pins */
-+	if (gpio_npins(ga->ga_mask) != SERVO_NPINS) {
-+		printf(": invalid pin mask\n");
-+		return;
-+	}
-+
-+	/* Map pins */
-+	sc->sc_gpio = ga->ga_gpio;
-+	sc->sc_map.pm_map = sc->__map;
-+	if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
-+	    &sc->sc_map)) {
-+		printf(": can't map pins\n");
-+		return;
-+	}
-+	
-+	/* Configure STEP pin (output). Initialize to LOW. */
-+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, SERVO_PIN_STEP);
-+	if (!(caps & GPIO_PIN_OUTPUT)) {
-+		printf(": STEP pin is unable to drive output\n");
-+		goto fail;
-+	}
-+	printf(": STEP[%d]", sc->sc_map.pm_map[SERVO_PIN_STEP]);
-+	ctl = GPIO_PIN_OUTPUT;
-+	if (caps & GPIO_PIN_PUSHPULL) { ctl |= GPIO_PIN_PUSHPULL; }
-+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, SERVO_PIN_STEP, ctl);
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SERVO_PIN_STEP, GPIO_PIN_LOW);
-+	sc->sc_step = 0;
-+	
-+	/* Configure DIR pin (output). Initialize to LOW. */
-+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, SERVO_PIN_DIR);
-+	if (!(caps & GPIO_PIN_OUTPUT)) {
-+		printf(": DIR pin is unable to drive output\n");
-+		goto fail;
-+	}
-+	printf(" DIR[%d]", sc->sc_map.pm_map[SERVO_PIN_DIR]);
-+	ctl = GPIO_PIN_OUTPUT;
-+	if (caps & GPIO_PIN_PUSHPULL) { ctl |= GPIO_PIN_PUSHPULL; }
-+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, SERVO_PIN_DIR, ctl);
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SERVO_PIN_DIR, GPIO_PIN_LOW);
-+	sc->sc_dir = 0;
-+
-+	printf("\n");
-+	return;
-+fail:
-+	gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
-+}
-+
-+int
-+servo_detach(struct device *self, int flags)
-+{
-+	return (cnc_device_detach(self));
-+}
-+
-+int
-+servo_activate(struct device *self, enum devact act)
-+{
-+	return (cnc_device_activate(self));
-+}
-+
-+void
-+servo_set_dir(void *arg, int dir)
-+{
-+	struct servo_softc *sc = arg;
-+
-+	if (sc->sc_dir != dir) {
-+		sc->sc_dir = dir;
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SERVO_PIN_DIR,
-+		    dir ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+	}
-+}
-+
-+void
-+servo_step(void *arg, int dir)
-+{
-+	struct servo_softc *sc = arg;
-+
-+	if (sc->sc_dir != dir) {
-+		sc->sc_dir = dir;
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SERVO_PIN_DIR,
-+		    (dir == 1) ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+	}
-+	sc->sc_step = !sc->sc_step;
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SERVO_PIN_STEP,
-+	    sc->sc_step ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+}
-+
-+#if 0
-+void
-+servo_accel_test(void *p)
-+{
-+	struct servo_softc *sc = p;
-+	int j, k, delay;
-+	int slow = 8000;
-+	int fast = 800;
-+	int steady = 10000;
-+	int accel = 100;
-+	int decel = 100;
-+
-+	printf("%s: velocity test\n", sc->sc_cdev.cd_dev.dv_xname);
-+
-+	delay = slow;
-+	k = 0;
-+	while (1) {
-+		sc->sc_step = !sc->sc_step;
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SERVO_PIN_STEP,
-+		    sc->sc_step ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+		for (j = 0; j < delay; j++)
-+			;;
-+		if (++k == accel) {
-+			k = 0;
-+			if (delay > fast) {
-+				delay -= 10;
-+			} else {
-+				if (--steady == 0)
-+					goto next;
-+			}
-+		}
-+	}
-+next:
-+	delay = fast;
-+	k = 0;
-+	while (1) {
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SERVO_PIN_STEP,
-+		    sc->sc_step ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+		for (j = 0; j < delay; j++)
-+			;;
-+		if (++k == decel) {
-+			k = 0;
-+			if (delay < slow) {
-+				delay += 10;
-+			} else {
-+				goto out;
-+			}
-+		}
-+	}
-+out:
-+	printf("%s: velocity test done\n", sc->sc_cdev.cd_dev.dv_xname);
-+	return;
-+}
-+#endif
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_servovar.h sys/dev/cnc/cnc_servovar.h
---- sys.ORIG/dev/cnc/cnc_servovar.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_servovar.h	Thu May 24 05:43:01 2007
- <at>  <at>  -0,0 +1,18  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*	Public domain	*/
-+
-+#define SERVO_NPINS		2
-+#define SERVO_PIN_STEP		0
-+#define SERVO_PIN_DIR		1
-+
-+struct servo_softc {
-+	struct cnc_device sc_cdev;
-+	void *sc_gpio;
-+	struct gpio_pinmap sc_map;
-+	int __map[SERVO_NPINS];
-+	int sc_step;				/* last step */
-+	int sc_dir;				/* last direction */
-+};
-+
-+void servo_set_dir(void *, int);
-+void servo_step(void *, int);
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_sin.S sys/dev/cnc/cnc_sin.S
---- sys.ORIG/dev/cnc/cnc_sin.S	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_sin.S	Mon May 21 11:41:14 2007
- <at>  <at>  -0,0 +1,25  <at>  <at> 
-+/*	$OpenBSD: s_sin.S,v 1.2 2005/08/02 11:17:31 espie Exp $ */
-+/*
-+ * Written by J.T. Conklin <jtc-S783fYmB3Ccdnm+yROfE0A <at> public.gmane.org>.
-+ * Public domain.
-+ */
-+
-+#include <machine/asm.h>
-+
-+ENTRY(cnc_sin)
-+	fldl	4(%esp)
-+	fsin
-+	fnstsw	%ax
-+	andw	$0x400,%ax
-+	jnz	1f
-+	ret
-+1:	fldpi
-+	fadd	%st(0)
-+	fxch	%st(1)
-+2:	fprem1
-+	fnstsw	%ax
-+	andw	$0x400,%ax
-+	jnz	2b
-+	fstp	%st(1)
-+	fsin
-+	ret
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_spindle.c sys/dev/cnc/cnc_spindle.c
---- sys.ORIG/dev/cnc/cnc_spindle.c	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_spindle.c	Sat May 26 23:21:14 2007
- <at>  <at>  -0,0 +1,303  <at>  <at> 
-+/*	$OpenBSD$	*/
-+
-+/*
-+ * Copyright (c) 2007 Hypertriton, Inc. <http://www.hypertriton.com/>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+ * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-+ * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+/*
-+ * Spindle controller with closed-loop control (direction output,
-+ * tachometer input and increment/decrement output signals).
-+ */
-+
-+#include <sys/param.h>
-+#include <sys/queue.h>
-+#include <sys/fcntl.h>
-+#include <sys/vnode.h>
-+#include <sys/systm.h>
-+#include <sys/kernel.h>
-+#include <sys/device.h>
-+#include <sys/pool.h>
-+#include <sys/conf.h>
-+#include <sys/lock.h>
-+
-+#include <sys/gpio.h>
-+#include <sys/cnc.h>
-+
-+#include <dev/gpio/gpiovar.h>
-+
-+#include <dev/cnc/cnc_devicevar.h>
-+#include <dev/cnc/cncvar.h>
-+#include <dev/cnc/cnc_spindlevar.h>
-+
-+int	spindle_match(struct device *, void *, void *);
-+void	spindle_attach(struct device *, struct device *, void *);
-+int	spindle_detach(struct device *, int);
-+int	spindle_activate(struct device *, enum devact);
-+
-+struct cfattach spindle_ca = {
-+	sizeof(struct spindle_softc),
-+	spindle_match,
-+	spindle_attach,
-+	spindle_detach,
-+	spindle_activate
-+};
-+
-+struct cfdriver spindle_cd = {
-+	NULL, "spindle", DV_DULL
-+};
-+
-+int
-+spindle_match(struct device *parent, void *match, void *aux)
-+{
-+	struct cfdata *cf = match;
-+
-+	return (strcmp(cf->cf_driver->cd_name, "spindle") == 0);
-+}
-+
-+void
-+spindle_attach(struct device *parent, struct device *self, void *aux)
-+{
-+	struct spindle_softc *sc = (struct spindle_softc *)self;
-+	struct gpio_attach_args *ga = aux;
-+	int caps, ctl;
-+
-+	/* Generic CNC device initialization. */
-+	if (cnc_device_attach(sc, CNC_DEVICE_SPINDLE) == -1)
-+		goto fail;
-+
-+	/* Check that we have enough pins */
-+	if (gpio_npins(ga->ga_mask) != SPINDLE_NPINS) {
-+		printf(": invalid pin mask\n");
-+		return;
-+	}
-+
-+	/* Map pins */
-+	sc->sc_gpio = ga->ga_gpio;
-+	sc->sc_map.pm_map = sc->__map;
-+	if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
-+	    &sc->sc_map)) {
-+		printf(": can't map pins\n");
-+		return;
-+	}
-+	
-+	/* Initialize DIR pin to LOW (CW) */
-+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DIR);
-+	if (!(caps & GPIO_PIN_OUTPUT)) {
-+		printf(": DIR pin is unable to drive output\n");
-+		goto fail;
-+	}
-+	printf(": DIR[%d]", sc->sc_map.pm_map[SPINDLE_PIN_DIR]);
-+	ctl = GPIO_PIN_OUTPUT;
-+	if (caps & GPIO_PIN_PUSHPULL) { ctl |= GPIO_PIN_PUSHPULL; }
-+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DIR, ctl);
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DIR, GPIO_PIN_LOW);
-+	sc->sc_dir = 1;
-+
-+	/* Initialize INCREMENT pin to LOW. */
-+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_INCREMENT);
-+	if (!(caps & GPIO_PIN_OUTPUT)) {
-+		printf(": INCREMENT pin is unable to drive output\n");
-+		goto fail;
-+	}
-+	printf(" INCREMENT[%d]", sc->sc_map.pm_map[SPINDLE_PIN_INCREMENT]);
-+	ctl = GPIO_PIN_OUTPUT;
-+	if (caps & GPIO_PIN_PUSHPULL) { ctl |= GPIO_PIN_PUSHPULL; }
-+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_INCREMENT, ctl);
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_INCREMENT,
-+	    GPIO_PIN_LOW);
-+
-+	/* Initialize DECREMENT pin to LOW. */
-+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DECREMENT);
-+	if (!(caps & GPIO_PIN_OUTPUT)) {
-+		printf(": DECREMENT pin is unable to drive output\n");
-+		goto fail;
-+	}
-+	printf(" DECREMENT[%d]", sc->sc_map.pm_map[SPINDLE_PIN_DECREMENT]);
-+	ctl = GPIO_PIN_OUTPUT;
-+	if (caps & GPIO_PIN_PUSHPULL) { ctl |= GPIO_PIN_PUSHPULL; }
-+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DECREMENT, ctl);
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DECREMENT,
-+	    GPIO_PIN_LOW);
-+
-+	/* Configure TACHO pin for input. */
-+	caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_TACHO);
-+	if (!(caps & GPIO_PIN_INPUT)) {
-+		printf(": TACHO pin is unable to read input\n");
-+		goto fail;
-+	}
-+	printf(" TACHO[%d]", sc->sc_map.pm_map[SPINDLE_PIN_TACHO]);
-+	ctl = GPIO_PIN_INPUT;
-+	gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_TACHO, ctl);
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_TACHO,
-+	    GPIO_PIN_LOW);
-+
-+	/* Initialize the structure. */
-+	sc->sc_speed = 0;
-+	sc->sc_speed_tacho = 0;
-+	sc->sc_speed_max = 3000;			/* XXX configure */
-+
-+	printf("\n");
-+	return;
-+fail:
-+	gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
-+}
-+
-+int
-+spindle_detach(struct device *self, int flags)
-+{
-+	return (cnc_device_detach(self));
-+}
-+
-+int
-+spindle_activate(struct device *self, enum devact act)
-+{
-+	return (cnc_device_activate(self));
-+}
-+
-+void
-+spindle_set_dir(void *arg, int dir)
-+{
-+	struct spindle_softc *sc = arg;
-+
-+	if (sc->sc_dir != dir) {
-+		sc->sc_dir = dir;
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DIR,
-+		    dir ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+	}
-+}
-+
-+void
-+spindle_step(void *arg, int dir)
-+{
-+	struct spindle_softc *sc = arg;
-+
-+	if (sc->sc_dir != dir) {
-+		sc->sc_dir = dir;
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_DIR,
-+		    dir ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+	}
-+	sc->sc_step = !sc->sc_step;
-+	gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_STEP,
-+	    sc->sc_step ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+}
-+
-+/*
-+ * Process CNC_SPINDLE_SPEED instruction. We do this by pulsing the
-+ * INCREMENT or DECREMENT pin until the tachometer returns the target
-+ * speed, within error.
-+ */
-+int
-+spindle_speed(void *p, struct cnc_insn *insn)
-+{
-+	struct spindle_softc *sc = p;
-+
-+	if (insn.i_spindle_speed > sc->sc_speed_max) {
-+		printf("%s: %u rpm exceeds spindle limit (%u)\n",
-+		    sc->sc_dev.dv_xname, insn.i_spindle_speed,
-+		    sc->sc_speed_max);
-+		return (EINVAL);
-+	}
-+	sc->sc_speed = insn.i_spindle_speed;
-+	/* TODO */
-+	return (0);
-+}
-+
-+/* Process CNC_SPINDLE_START instruction. */
-+/* XXX block until target speed is reached? */
-+int
-+spindle_start(void *p, struct cnc_insn *insn)
-+{
-+	struct spindle_softc *sc = p;
-+
-+	/* TODO */
-+	printf("%s: startup\n", sc->sc_dev.dv_xname);
-+	return (0);
-+}
-+
-+/* Process CNC_SPINDLE_STOP instruction. */
-+/* XXX block until target speed is reached? */
-+int
-+spindle_stop(void *p, struct cnc_insn *insn)
-+{
-+	struct spindle_softc *sc = p;
-+
-+	/* TODO */
-+	printf("%s: spindle stopped\n", sc->sc_dev.dv_xname);
-+	return (0);
-+}
-+
-+#if 0
-+void
-+spindle_accel_test(void *p)
-+{
-+	struct spindle_softc *sc = p;
-+	int j, k, delay;
-+	int slow = 8000;
-+	int fast = 800;
-+	int steady = 10000;
-+	int accel = 100;
-+	int decel = 100;
-+
-+	printf("%s: velocity test\n", sc->sc_cdev.cd_dev.dv_xname);
-+
-+	delay = slow;
-+	k = 0;
-+	while (1) {
-+		sc->sc_step = !sc->sc_step;
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_STEP,
-+		    sc->sc_step ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+		for (j = 0; j < delay; j++)
-+			;;
-+		if (++k == accel) {
-+			k = 0;
-+			if (delay > fast) {
-+				delay -= 10;
-+			} else {
-+				if (--steady == 0)
-+					goto next;
-+			}
-+		}
-+	}
-+next:
-+	delay = fast;
-+	k = 0;
-+	while (1) {
-+		gpio_pin_write(sc->sc_gpio, &sc->sc_map, SPINDLE_PIN_STEP,
-+		    sc->sc_step ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-+		for (j = 0; j < delay; j++)
-+			;;
-+		if (++k == decel) {
-+			k = 0;
-+			if (delay < slow) {
-+				delay += 10;
-+			} else {
-+				goto out;
-+			}
-+		}
-+	}
-+out:
-+	printf("%s: velocity test done\n", sc->sc_cdev.cd_dev.dv_xname);
-+	return;
-+}
-+#endif
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_spindlevar.h sys/dev/cnc/cnc_spindlevar.h
---- sys.ORIG/dev/cnc/cnc_spindlevar.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_spindlevar.h	Sat May 26 23:21:03 2007
- <at>  <at>  -0,0 +1,23  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*	Public domain	*/
-+
-+#define SPINDLE_NPINS		4
-+#define SPINDLE_PIN_DIR		0	/* direction signal (0=CW, 1=CCW) */
-+#define SPINDLE_PIN_TACHO	1	/* tachometer input (1 pulse/rev) */
-+#define SPINDLE_PIN_INCREMENT	2	/* speed controller increment */
-+#define SPINDLE_PIN_DECREMENT	3	/* speed controller decrement */
-+
-+struct spindle_softc {
-+	struct cnc_device sc_cdev;
-+	void *sc_gpio;
-+	struct gpio_pinmap sc_map;
-+	int __map[SERVO_NPINS];
-+	int sc_dir;			/* current direction (1=CW, -1=CCW) */
-+	int sc_speed;			/* desired speed (rpm) */
-+	u_int sc_speed_tacho;		/* last measured speed (rpm) */
-+	u_int sc_speed_max;		/* maximum allowed speed (rpm) */
-+};
-+
-+int spindle_speed(void *, struct cnc_insn *);
-+int spindle_start(void *, struct cnc_insn *);
-+int spindle_stop(void *, struct cnc_insn *);
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cnc_sqrt.S sys/dev/cnc/cnc_sqrt.S
---- sys.ORIG/dev/cnc/cnc_sqrt.S	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cnc_sqrt.S	Tue May 22 05:05:54 2007
- <at>  <at>  -0,0 +1,12  <at>  <at> 
-+/*	$OpenBSD: e_sqrt.S,v 1.2 2005/08/02 11:17:31 espie Exp $ */
-+/*
-+ * Written by J.T. Conklin <jtc-S783fYmB3Ccdnm+yROfE0A <at> public.gmane.org>.
-+ * Public domain.
-+ */
-+
-+#include <machine/asm.h>
-+
-+ENTRY(cnc_sqrt)
-+	fldl	4(%esp)
-+	fsqrt
-+	ret
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/cncvar.h sys/dev/cnc/cncvar.h
---- sys.ORIG/dev/cnc/cncvar.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/cncvar.h	Thu Jun  7 03:21:45 2007
- <at>  <at>  -0,0 +1,34  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*	Public domain	*/
-+
-+#include "cnc_math.h"
-+#include "cnc_quintic.h"
-+
-+extern const char *cnc_insn_names[];
-+extern struct cnc_device *cnc_servos[CNC_NAXES];
-+extern struct cnc_device *cnc_spindles[CNC_MAX_SPINDLES];
-+extern struct cnc_device *cnc_estops[CNC_MAX_ESTOPS];
-+extern int cnc_nservos;
-+extern int cnc_nspindles;
-+extern int cnc_nestops;
-+extern u_long cnc_timebase;
-+
-+int cncopen(dev_t, int, int, struct proc *);
-+int cncclose(dev_t, int, int, struct proc *);
-+int cncioctl(dev_t, u_long, caddr_t, int, struct proc *);
-+int cncwrite(dev_t, struct uio *, int);
-+void cncattach(int);
-+int cncdetach(struct device *, int);
-+int cncactivate(struct device *, enum devact);
-+
-+void cnc_cal_update(void *);
-+int cnc_move(struct cnc_insn *);
-+int cnc_prog_exec(void);
-+void cnc_prog_reset(void);
-+__inline void cnc_move_axis(enum cnc_axis, int);
-+__inline struct cnc_device *cnc_get_spindle(int);
-+__inline void cnc_move_delay(const struct cnc_quintic_profile *, cnc_real_t,
-+                             cnc_real_t);
-+u_long cnc_calibrate_timebase(void);
-+__inline int cnc_estop_raised(void);
-+
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/files.cnc sys/dev/cnc/files.cnc
---- sys.ORIG/dev/cnc/files.cnc	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/files.cnc	Tue Jun  5 00:30:31 2007
- <at>  <at>  -0,0 +1,33  <at>  <at> 
-+# $OpenBSD$
-+
-+# CNC controller interface.
-+pseudo-device	cnc
-+file	dev/cnc/cnc.c			cnc needs-flag
-+file	dev/cnc/cnc_device.c		cnc needs-flag
-+file	dev/cnc/cnc_math.c		cnc needs-flag
-+file	dev/cnc/cnc_sin.S		cnc needs-flag
-+file	dev/cnc/cnc_sqrt.S		cnc needs-flag
-+file	dev/cnc/cnc_cbrt.c		cnc needs-flag
-+file	dev/cnc/cnc_log10.S		cnc needs-flag
-+file	dev/cnc/cnc_modf.c		cnc needs-flag
-+file	dev/cnc/cnc_quintic.c		cnc needs-flag
-+
-+# Servo or stepping motor with clock/direction interface.
-+device	servo
-+attach	servo at gpio
-+file	dev/cnc/cnc_servo.c		servo		needs-flag
-+
-+# Machine tool spindle controller.
-+device	spindle
-+attach	spindle at gpio
-+file	dev/cnc/cnc_spindle.c		spindle		needs-flag
-+
-+# Control panel for CNC machining equipment.
-+device	cncpanel
-+attach	cncpanel at gpio
-+file	dev/cnc/cnc_panel.c		cncpanel	needs-flag
-+
-+# Emergency stop button and/or limit switches.
-+device	estop
-+attach	estop at gpio
-+file	dev/cnc/cnc_estop.c		estop		needs-flag
-diff -uNr --exclude=.svn sys.ORIG/dev/cnc/math_private.h sys/dev/cnc/math_private.h
---- sys.ORIG/dev/cnc/math_private.h	Wed Dec 31 20:00:00 1969
-+++ sys/dev/cnc/math_private.h	Wed May 30 00:13:18 2007
- <at>  <at>  -0,0 +1,154  <at>  <at> 
-+/*	$OpenBSD: math_private.h,v 1.6 2002/02/16 21:27:27 millert Exp $	*/
-+/*
-+ * ====================================================
-+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-+ *
-+ * Developed at SunPro, a Sun Microsystems, Inc. business.
-+ * Permission to use, copy, modify, and distribute this
-+ * software is freely granted, provided that this notice 
-+ * is preserved.
-+ * ====================================================
-+ */
-+
-+/*
-+ * from:  <at> (#)fdlibm.h 5.1 93/09/24
-+ */
-+
-+#ifndef _MATH_PRIVATE_H_
-+#define _MATH_PRIVATE_H_
-+
-+#include <sys/types.h>
-+
-+/* The original fdlibm code used statements like:
-+	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
-+	ix0 = *(n0+(int*)&x);			* high word of x *
-+	ix1 = *((1-n0)+(int*)&x);		* low word of x *
-+   to dig two 32 bit words out of the 64 bit IEEE floating point
-+   value.  That is non-ANSI, and, moreover, the gcc instruction
-+   scheduler gets it wrong.  We instead use the following macros.
-+   Unlike the original code, we determine the endianness at compile
-+   time, not at run time; I don't see much benefit to selecting
-+   endianness at run time.  */
-+
-+/* A union which permits us to convert between a double and two 32 bit
-+   ints.  */
-+
-+/*
-+ * The arm32 port is little endian except for the FP word order which is
-+ * big endian.
-+ */
-+
-+#if (BYTE_ORDER == BIG_ENDIAN) || defined(arm32)
-+
-+typedef union 
-+{
-+  double value;
-+  struct 
-+  {
-+    u_int32_t msw;
-+    u_int32_t lsw;
-+  } parts;
-+} ieee_double_shape_type;
-+
-+#endif
-+
-+#if (BYTE_ORDER == LITTLE_ENDIAN) && !defined(arm32)
-+
-+typedef union 
-+{
-+  double value;
-+  struct 
-+  {
-+    u_int32_t lsw;
-+    u_int32_t msw;
-+  } parts;
-+} ieee_double_shape_type;
-+
-+#endif
-+
-+/* Get two 32 bit ints from a double.  */
-+
-+#define EXTRACT_WORDS(ix0,ix1,d)				\
-+do {								\
-+  ieee_double_shape_type ew_u;					\
-+  ew_u.value = (d);						\
-+  (ix0) = ew_u.parts.msw;					\
-+  (ix1) = ew_u.parts.lsw;					\
-+} while (0)
-+
-+/* Get the more significant 32 bit int from a double.  */
-+
-+#define GET_HIGH_WORD(i,d)					\
-+do {								\
-+  ieee_double_shape_type gh_u;					\
-+  gh_u.value = (d);						\
-+  (i) = gh_u.parts.msw;						\
-+} while (0)
-+
-+/* Get the less significant 32 bit int from a double.  */
-+
-+#define GET_LOW_WORD(i,d)					\
-+do {								\
-+  ieee_double_shape_type gl_u;					\
-+  gl_u.value = (d);						\
-+  (i) = gl_u.parts.lsw;						\
-+} while (0)
-+
-+/* Set a double from two 32 bit ints.  */
-+
-+#define INSERT_WORDS(d,ix0,ix1)					\
-+do {								\
-+  ieee_double_shape_type iw_u;					\
-+  iw_u.parts.msw = (ix0);					\
-+  iw_u.parts.lsw = (ix1);					\
-+  (d) = iw_u.value;						\
-+} while (0)
-+
-+/* Set the more significant 32 bits of a double from an int.  */
-+
-+#define SET_HIGH_WORD(d,v)					\
-+do {								\
-+  ieee_double_shape_type sh_u;					\
-+  sh_u.value = (d);						\
-+  sh_u.parts.msw = (v);						\
-+  (d) = sh_u.value;						\
-+} while (0)
-+
-+/* Set the less significant 32 bits of a double from an int.  */
-+
-+#define SET_LOW_WORD(d,v)					\
-+do {								\
-+  ieee_double_shape_type sl_u;					\
-+  sl_u.value = (d);						\
-+  sl_u.parts.lsw = (v);						\
-+  (d) = sl_u.value;						\
-+} while (0)
-+
-+/* A union which permits us to convert between a float and a 32 bit
-+   int.  */
-+
-+typedef union
-+{
-+  float value;
-+  u_int32_t word;
-+} ieee_float_shape_type;
-+
-+/* Get a 32 bit int from a float.  */
-+
-+#define GET_FLOAT_WORD(i,d)					\
-+do {								\
-+  ieee_float_shape_type gf_u;					\
-+  gf_u.value = (d);						\
-+  (i) = gf_u.word;						\
-+} while (0)
-+
-+/* Set a float from a 32 bit int.  */
-+
-+#define SET_FLOAT_WORD(d,i)					\
-+do {								\
-+  ieee_float_shape_type sf_u;					\
-+  sf_u.word = (i);						\
-+  (d) = sf_u.value;						\
-+} while (0)
-+
-+#endif /* _MATH_PRIVATE_H_ */
-diff -uNr --exclude=.svn sys.ORIG/sys/cnc.h sys/sys/cnc.h
---- sys.ORIG/sys/cnc.h	Wed Dec 31 20:00:00 1969
-+++ sys/sys/cnc.h	Thu Jun  7 03:12:20 2007
- <at>  <at>  -0,0 +1,135  <at>  <at> 
-+/*	$OpenBSD$	*/
-+/*	Public domain	*/
-+
-+#ifndef _SYS_CNC_H_
-+#define _SYS_CNC_H_
-+
-+#include <sys/stdint.h>
-+
-+#define CNC_BUF_SIZE		1024		/* size of instruction buffer */
-+#define CNC_MAX_AXES		3		/* max axes (min. 1) */
-+#define CNC_NAXES		CNC_MAX_AXES
-+#define CNC_MAX_SPINDLES	2		/* max spindles */
-+#define CNC_MAX_ESTOPS		13		/* max e-stops/limit switches */
-+
-+enum cnc_axis {
-+	CNC_X, CNC_Y, CNC_Z,
-+	CNC_A, CNC_B, CNC_C
-+};
-+
-+typedef uint64_t cnc_step_t;
-+typedef int64_t cnc_pos_t;
-+typedef int64_t cnc_time_t;
-+
-+enum cnc_insn_type {
-+	/* servo(4) operations */
-+	CNC_MOVE,			/* coordinated move to given position */
-+	CNC_SET_INTERP,			/* set interpolation mode */
-+	/* spindle(4) operations */
-+	CNC_SPINDLE_DIR,		/* change current direction */
-+	CNC_SPINDLE_SPEED,		/* set revolutions per minute */
-+	CNC_SPINDLE_START,		/* start spindle rotation */
-+	CNC_SPINDLE_STOP,		/* stop spindle rotation */
-+	/* atc(4) operations */
-+	CNC_ATC_PREPARE,		/* prepare tool for next change */
-+	CNC_ATC_CHANGE,			/* change tool in spindle */
-+	/* laser(4) operations */
-+	CNC_LASER_ON,			/* TTL trigger high */
-+	CNC_LASER_OFF,			/* TTL trigger low */
-+	CNC_LASER_CURRENT,		/* set steady-state current */
-+	/* pickplace(4) operations */
-+	CNC_PICKPLACE_REEL,		/* advance specified reel */
-+	CNC_PICKPLACE_SUCTION,		/* enable suction cup vacuum */
-+	CNC_PICKPLACE_RELEASE,		/* release suction cup vacuum */
-+	/* miscellaneous */
-+	CNC_PREEMPT,			/* delay (with interrupts reenabled) */
-+	CNC_DWELL,			/* precise delay (no interrupts) */
-+	CNC_COOL_MIST,			/* toggle mist coolant */
-+	CNC_COOL_FLOOD,			/* toggle flood or thru-tool coolant */
-+	CNC_COOL_VORTEX,		/* toggle vortex tube */
-+	CNC_LAST_INSN
-+};
-+
-+/* Mode of interpolation between coordinates */
-+enum cnc_interp_mode {
-+	CNC_INTERP_LINEAR,		/* linear interpolation */
-+	CNC_INTERP_LAST
-+};
-+
-+/* Velocity curve generation algorithm */
-+enum cnc_velocity_mode {
-+	CNC_VEL_BLENDED_SCURVE,		/* blended s-curve (second-order) */
-+	CNC_VEL_SQUARED_SINE,		/* squared sine (third-order) */
-+};
-+
-+/* Position vector */
-+typedef struct cnc_vector {
-+	cnc_pos_t v[CNC_NAXES];
-+} cnc_vec_t;
-+
-+/*
-+ * Kinematic limits. These values must be adjusted based on the physical
-+ * limits of the motors and of the load they are driving.
-+ */
-+struct cnc_kinematics {
-+	int k_Ts;		/* third-order jerk limit (ms) */
-+	int k_Vmax;		/* maximum velocity (steps/sec) */
-+};
-+
-+/* Program instruction */
-+struct cnc_insn {
-+	enum cnc_insn_type i_type;
-+	union {
-+		struct {
-+			cnc_vec_t i_pos; /* relative target coords */
-+			u_long i_v0;	 /* minimum velocity (steps/s) */
-+			u_long i_F;	 /* maximum velocity (steps/s) */
-+			u_long i_Amax;	 /* max acceleration (steps/ms^2) */
-+			u_long i_Jmax;	 /* max jerk (steps/ms^3) */
-+		} i_move;
-+		struct {
-+			int i_id;	/* name of spindle */
-+			int i_dir;	/* 1=CW, -1=CCW */
-+			u_int i_speed;	/* speed in RPM */
-+		} i_spindle;
-+		enum cnc_interp_mode i_interp_mode; /* for SET_INTERP */
-+		cnc_step_t i_delay;		    /* for DWELL and PREEMPT */
-+		struct {
-+			int i_atc_id;		/* name of ATC controller */
-+			int i_tool_idx;		/* name of tool */
-+			int i_tgt_spindle;	/* name of target spindle */
-+		} i_atc;
-+		int i_laser_current;		/* for LASER_CURRENT */
-+		int i_pickplace_reel;		/* for PICKPLACE_REEL */
-+	} i_arg;
-+#define i_pos			i_arg.i_move.i_pos
-+#define i_F			i_arg.i_move.i_F
-+#define i_v0			i_arg.i_move.i_v0
-+#define i_Amax			i_arg.i_move.i_Amax
-+#define i_Jmax			i_arg.i_move.i_Jmax
-+#define i_interp_mode		i_arg.i_interp_mode
-+#define i_spindle_id		i_arg.i_spindle.i_id
-+#define i_spindle_dir		i_arg.i_spindle.i_dir
-+#define i_spindle_speed		i_arg.i_spindle.i_speed
-+#define i_delay			i_arg.i_delay
-+#define i_atc_id		i_arg.i_atc.i_atc_id
-+#define i_atc_tool_idx		i_arg.i_atc.i_tool_idx
-+#define i_atc_tgt_spindle	i_arg.i_atc.i_tgt_spindle
-+#define i_laser_current		i_arg.i_laser_current
-+	TAILQ_ENTRY(cnc_insn) prog;
-+};
-+
-+#define CNC_EXECPROG		_IO('C', 0)
-+#define CNC_RESETPROG		_IO('C', 1)
-+#define CNC_GETPOS		_IOR('C', 2, struct cnc_vector)
-+#define CNC_SETPOS		_IOWR('C', 3, struct cnc_vector)
-+#define CNC_GETNSERVOS		_IOR('C', 4, int)
-+#define CNC_GETNSPINDLES	_IOR('C', 5, int)
-+#define CNC_GETKINLIMITS	_IOR('C', 6, struct cnc_kinematics)
-+#define CNC_SETKINLIMITS	_IOWR('C', 7, struct cnc_kinematics)
-+#define CNC_GETTIMEBASE		_IOR('C', 8, u_long)
-+#define CNC_SETTIMEBASE		_IOWR('C', 9, u_long)
-+#define CNC_CALTIMEBASE		_IOWR('C', 10, u_long)
-+#define CNC_GETNESTOPS		_IOR('C', 11, int)
-+
-+#endif	/* !_SYS_CNC_H_ */
 diff -uNr --exclude=.svn sys.ORIG/sys/conf.h sys/sys/conf.h
 --- sys.ORIG/sys/conf.h	Tue Aug  1 07:14:38 2006
 +++ sys/sys/conf.h	Thu Apr 26 08:51:48 2007

Gmane