diff -ru slmodem-2.9.10.orig/modem/Makefile slmodem-2.9.10/modem/Makefile
--- slmodem-2.9.10.orig/modem/Makefile	Thu Nov 20 06:50:47 2003
+++ slmodem-2.9.10/modem/Makefile	Sat Jul  2 02:46:50 2005
@@ -37,6 +37,17 @@
 CFLAGS+= -DSUPPORT_ALSA=1
 endif
 
+#SUPPORT_NETBSD:=1
+ifdef SUPPORT_NETBSD
+CFLAGS+= -DSUPPORT_NETBSD=1
+endif
+
+SUPPORT_FREEBSD:=1
+ifdef SUPPORT_FREEBSD
+slmodemd modem_test: getpt.o -lutil
+CFLAGS+= -DSUPPORT_FREEBSD=1
+endif
+
 slmodemd modem_test:
 	$(CC) -o $@ $^
 
diff -ru slmodem-2.9.10.orig/modem/getpt.c slmodem-2.9.10/modem/getpt.c
--- slmodem-2.9.10.orig/modem/getpt.c	Sat Jul  2 12:37:22 2005
+++ slmodem-2.9.10/modem/getpt.c	Sat Jul  2 12:36:56 2005
@@ -0,0 +1,21 @@
+/* http://mail.gnome.org/archives/system-tools-list/2001-May/msg00092.html */
+#ifdef	__FreeBSD__
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <libutil.h>
+#include <errno.h>
+
+int
+getpt(void)
+{
+	int master, slave;
+
+	if(openpty(&master, &slave, NULL, NULL, NULL) < 0){
+		errno = ENOENT;
+		return -1;
+	}
+	return master;
+}
+#endif
diff -ru slmodem-2.9.10.orig/modem/modem_cmdline.c slmodem-2.9.10/modem/modem_cmdline.c
--- slmodem-2.9.10.orig/modem/modem_cmdline.c	Sun Aug  8 08:26:53 2004
+++ slmodem-2.9.10/modem/modem_cmdline.c	Sat Jul  2 03:05:22 2005
@@ -74,7 +74,13 @@
 unsigned int ring_detector = 0;
 #endif
 unsigned int use_alsa = 0;
+unsigned int use_netbsd = 0;
+unsigned int use_freebsd = 0;
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+const char *modem_group = "tty";
+#else
 const char *modem_group = "uucp";
+#endif
 mode_t modem_perm  = 0660;
 
 
@@ -85,6 +91,8 @@
 	OPT_COUNTRY,
 	OPT_COUNTRYLIST,
 	OPT_ALSA,
+	OPT_NETBSD,
+	OPT_FREEBSD,
 	OPT_GROUP,
 	OPT_PERM,
 #ifdef MODEM_CONFIG_RING_DETECTOR
@@ -111,7 +119,13 @@
 	{'c',"country","default modem country name",MANDATORY,STRING,"USA"},
 	{ 0 ,"countrylist","show list of supported countries"},
 	{'a',"alsa","ALSA mode (see README for howto)"},
+	{'b',"netbsd","NetBSD mode (see README for howto)",OPTIONAL,STRING,"/dev/sound1"},
+	{'f',"freebsd","FreeBSD mode (see README for howto)",OPTIONAL,STRING,"/dev/dsp1"},
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+	{'g',"group","Modem TTY group",MANDATORY,STRING,"tty"},
+#else
 	{'g',"group","Modem TTY group",MANDATORY,STRING,"uucp"},
+#endif
 	{'p',"perm","Modem TTY permission",MANDATORY,INTEGER,"0660"},
 #ifdef MODEM_CONFIG_RING_DETECTOR
 	{'r',"ringdetector","with internal ring detector (software)"},
@@ -248,6 +262,22 @@
 		exit(1);
 #endif
 		use_alsa = 1;
+	}
+	if(opt_list[OPT_NETBSD].found) {
+#ifndef SUPPORT_NETBSD
+		PR_INFO("NetBSD support is not compiled in (see README for howto).\n");
+		exit(1);
+#endif
+		modem_dev_name = opt_list[OPT_NETBSD].arg_val;
+		use_netbsd = 1;
+	}
+	if(opt_list[OPT_FREEBSD].found) {
+#ifndef SUPPORT_FREEBSD
+		PR_INFO("FreeBSD support is not compiled in (see README for howto).\n");
+		exit(1);
+#endif
+		modem_dev_name = opt_list[OPT_FREEBSD].arg_val;
+		use_freebsd = 1;
 	}
 	if(opt_list[OPT_GROUP].found)
 		modem_group = opt_list[OPT_GROUP].arg_val;
diff -ru slmodem-2.9.10.orig/modem/modem_main.c slmodem-2.9.10/modem/modem_main.c
--- slmodem-2.9.10.orig/modem/modem_main.c	Sun Aug  8 08:26:53 2004
+++ slmodem-2.9.10/modem/modem_main.c	Sat Jul  2 04:39:17 2005
@@ -57,6 +57,9 @@
 #include <signal.h>
 #include <limits.h>
 #include <grp.h>
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#include <libgen.h>
+#endif
 
 #ifdef SUPPORT_ALSA
 #define ALSA_PCM_NEW_HW_PARAMS_API 1
@@ -64,6 +67,14 @@
 #include <alsa/asoundlib.h>
 #endif
 
+#ifdef SUPPORT_NETBSD
+#include <sys/audioio.h>
+#endif
+
+#ifdef SUPPORT_FREEBSD
+#include <sys/soundcard.h>
+#endif
+
 #include <modem.h>
 #include <modem_debug.h>
 
@@ -104,6 +115,15 @@
 	unsigned int period;
 	unsigned int started;
 #endif
+#ifdef SUPPORT_NETBSD
+	audio_info_t info;
+	unsigned int period;
+	unsigned int started;
+#endif
+#ifdef SUPPORT_FREEBSD
+	unsigned int period;
+	unsigned int started;
+#endif
 	int delay;
 };
 
@@ -457,6 +477,463 @@
 
 
 /*
+ *    NetBSD 'driver'
+ *
+ */
+#ifdef SUPPORT_NETBSD
+#define INTERNAL_DELAY 40
+
+extern unsigned use_netbsd;
+static int netbsd_audio_setup(struct device_struct *);
+
+static int netbsd_device_setup(struct device_struct *dev, const char *dev_name)
+{
+	//int ioctlarg;
+
+	DBG("netbsd device setup\n");
+	dev->num = 0;
+	dev->fd = open(dev_name, O_RDWR|O_NONBLOCK);
+	if (dev->fd < 0) {
+		ERR("netbsd setup: cannot open playback device '%s': %s\n",
+		    dev_name, strerror(errno));
+		return -1;
+	}
+
+	return netbsd_audio_setup(dev);
+}
+
+static int netbsd_device_release(struct device_struct *dev)
+{
+
+	DBG("netbsd device release\n");
+	close(dev->fd);
+
+	return 0;
+}
+
+static int netbsd_xrun_recovery(struct device_struct *dev)
+{
+	int err;
+	int len;
+	int x;
+	char *buf;
+
+	DBG("netbsd xrun: try to recover...\n");
+	len = dev->delay - INTERNAL_DELAY;
+	buf = outbuf;
+	bzero(buf, len);
+	while (len > 0) {
+		x = write(dev->fd, buf, len);
+		len -= x;
+		buf += x;
+	}
+	
+	DBG("netbsd xrun recovery: recovered.\n");
+	return 0;
+}
+
+
+static int netbsd_device_read(struct device_struct *dev, char *buf, int len)
+{
+	int ret;
+	int x;
+
+	//DBG("netbsd device read\n");
+
+	while (len > 0) {
+		x = read(dev->fd, buf, len);
+		//DBG("netbsd device read: read returns %d, errno=%d\n", x, errno);
+		if (x == -1 && errno == EAGAIN) {
+			//ret = netbsd_xrun_recovery(dev);
+			continue;
+		}
+		if (x == -1) {
+			DBG("netbsd device read: %s\n", strerror(errno));
+		} else {
+			buf += x;
+			len -= x;
+		}
+	}
+
+	if(ret != dev->period)
+		DBG("netbsd device read (%d): %d ...\n", len, ret);
+
+	return ret;
+}
+
+static int netbsd_device_write(struct device_struct *dev, const char *buf, int count)
+{
+	int asked = count;
+	int written = 0;
+
+	//DBG("netbsd device write\n");
+	if(!dev->started)
+		return 0;
+
+	while(count > 0) {
+		int ret = write(dev->fd, buf, count);
+		if(ret < 0) {
+			//DBG("netbsd device write: %s\n", strerror(errno));
+			if (errno == EAGAIN)
+				continue;
+			if (errno == EPIPE) {
+			    	//ret = netbsd_xrun_recovery(dev);
+			}
+			written = ret;
+			break;
+		}
+		count -= ret;
+		buf += ret;
+		written += ret;
+	}
+
+	if(written != dev->period)
+		DBG("netbsd device write (%d): %d...\n",asked,written);
+
+	return written;
+}
+
+static int netbsd_start (struct modem *m)
+{
+	struct device_struct *dev = m->dev_data;
+	int err, len;
+	int pos;
+	int rv;
+
+	DBG("netbsd start...\n");
+	dev->period = m->frag;
+	dev->delay = 0;
+	len = 384;           /* <-- FIXME */
+
+	rv = netbsd_audio_setup(dev);
+	dev->started = 1;
+
+	return rv;
+}
+
+static int
+netbsd_audio_setup(struct device_struct *dev) {
+	audio_info_t oinfo;
+	int is_full_duplex = 1;
+	char *buf;
+
+	DBG("netbsd audio setup: GETINFO\n");
+	if (ioctl(dev->fd, AUDIO_GETINFO, &oinfo) < 0) {
+		ERR("netbsd audio setup: ioctl(AUDIO_GETINFO) failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	DBG("netbsd audio setup: AUDIO_INITINFO\n");
+	AUDIO_INITINFO(&dev->info);
+	dev->info.play.sample_rate = dev->info.record.sample_rate = 8000;
+	dev->info.play.channels = dev->info.record.channels = 1;
+	dev->info.play.precision = dev->info.record.precision = 16;
+	dev->info.play.encoding = dev->info.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
+	dev->info.play.gain = dev->info.record.gain = oinfo.play.gain;
+	dev->info.play.port = dev->info.record.port = oinfo.play.port;
+	dev->info.play.balance = dev->info.record.balance = oinfo.play.balance;
+	dev->info.monitor_gain = oinfo.monitor_gain;
+	dev->info.mode = AUMODE_PLAY | AUMODE_RECORD;
+
+	if (ioctl(dev->fd, AUDIO_SETINFO, &dev->info) < 0) {
+		ERR("netbsd start: ioctl(AUDIO_SETINFO) failed: %s\n", strerror(errno));
+		return -1;
+	}
+	if (ioctl(dev->fd, AUDIO_SETFD, &is_full_duplex) < 0) {
+		ERR("netbsd start: ioctl(AUDIO_SETFD) failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* XXX workaround a NetBSD bug */
+	buf = outbuf;
+	bzero(buf, 1);
+	netbsd_device_read(dev, buf, 1);
+	
+	dev->delay = 0;
+	dev->delay += INTERNAL_DELAY; /* <-- fixme: delay detection is needed */
+
+	DBG("started\n");
+	return 0;
+}
+
+static int netbsd_stop (struct modem *m)
+{
+	struct device_struct *dev = m->dev_data;
+	DBG("netbsd stop...\n");
+	dev->started = 0;
+	ioctl(dev->fd, AUDIO_DRAIN, NULL);
+	return 0;
+}
+
+static int netbsd_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
+{
+	/* TODO */
+	struct device_struct *dev = m->dev_data;
+	DBG("netbsd ioctl: cmd %x, arg %lx...\n",cmd,arg);
+	switch(cmd) {
+        case MDMCTL_CAPABILITIES:
+                return -EINVAL;
+        case MDMCTL_HOOKSTATE:
+                return 0;
+        case MDMCTL_CODECTYPE:
+                return CODEC_SILABS;
+        case MDMCTL_IODELAY:
+		DBG("delay = %d\n", dev->delay);
+		return dev->delay;
+#if 0
+	case MDMCTL_SPEED:
+		DBG("speed = %d\n", arg);
+		dev->info.play.sample_rate = dev->info.record.sample_rate = arg;
+		ioctl(dev->fd, AUDIO_SETINFO, &dev->info);
+		return 0;
+#endif
+	default:
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct modem_driver netbsd_modem_driver = {
+        .name = "netbsd modem driver",
+        .start = netbsd_start,
+        .stop = netbsd_stop,
+        .ioctl = netbsd_ioctl,
+};
+
+#endif /* !SUPPORT_NETBSD */
+
+
+/*
+ *    FreeBSD 'driver'
+ *
+ */
+#ifdef SUPPORT_FREEBSD
+#define INTERNAL_DELAY 40
+
+extern unsigned use_freebsd;
+static int freebsd_audio_setup(struct device_struct *);
+
+static int freebsd_device_setup(struct device_struct *dev, const char *dev_name)
+{
+	//int ioctlarg;
+
+	DBG("freebsd device setup\n");
+	dev->num = 0;
+	dev->fd = open(dev_name, O_RDWR|O_NONBLOCK|O_NDELAY);
+	if (dev->fd < 0) {
+		ERR("freebsd setup: cannot open playback device '%s': %s\n",
+		    dev_name, strerror(errno));
+		return -1;
+	}
+
+	return freebsd_audio_setup(dev);
+}
+
+static int freebsd_device_release(struct device_struct *dev)
+{
+
+	DBG("freebsd device release\n");
+	close(dev->fd);
+
+	return 0;
+}
+
+static int freebsd_xrun_recovery(struct device_struct *dev)
+{
+	int err;
+	int len;
+	int x;
+	char *buf;
+
+	DBG("freebsd xrun: try to recover...\n");
+	len = dev->delay - INTERNAL_DELAY;
+	buf = outbuf;
+	bzero(buf, len);
+	while (len > 0) {
+		x = write(dev->fd, buf, len);
+		len -= x;
+		buf += x;
+	}
+	
+	DBG("freebsd xrun recovery: recovered.\n");
+	return 0;
+}
+
+
+static int freebsd_device_read(struct device_struct *dev, char *buf, int len)
+{
+	int ret;
+	int x;
+
+	//DBG("freebsd device read\n");
+
+	while (len > 0) {
+		x = read(dev->fd, buf, len);
+		//DBG("freebsd device read: read returns %d, errno=%d\n", x, errno);
+		if (x == -1 && errno == EAGAIN) {
+			//ret = freebsd_xrun_recovery(dev);
+			continue;
+		}
+		if (x == -1) {
+			DBG("freebsd device read: %s\n", strerror(errno));
+		} else {
+			buf += x;
+			len -= x;
+		}
+	}
+
+	if(ret != dev->period)
+		DBG("freebsd device read (%d): %d ...\n", len, ret);
+
+	return ret;
+}
+
+static int freebsd_device_write(struct device_struct *dev, const char *buf, int count)
+{
+	int asked = count;
+	int written = 0;
+
+	//DBG("freebsd device write\n");
+	if(!dev->started)
+		return 0;
+
+	while(count > 0) {
+		int ret = write(dev->fd, buf, count);
+		if(ret < 0) {
+			//DBG("freebsd device write: %s\n", strerror(errno));
+			if (errno == EAGAIN)
+				continue;
+			if (errno == EPIPE) {
+			    	//ret = freebsd_xrun_recovery(dev);
+			}
+			written = ret;
+			break;
+		}
+		count -= ret;
+		buf += ret;
+		written += ret;
+	}
+
+	if(written != dev->period)
+		DBG("freebsd device write (%d): %d...\n",asked,written);
+
+	return written;
+}
+
+static int freebsd_start (struct modem *m)
+{
+	struct device_struct *dev = m->dev_data;
+	int err, len;
+	int pos;
+	int rv;
+
+	DBG("freebsd start...\n");
+	dev->period = m->frag;
+	dev->delay = 0;
+	len = 384;           /* <-- FIXME */
+
+	rv = freebsd_audio_setup(dev);
+	dev->started = 1;
+
+	return rv;
+}
+
+static int
+freebsd_audio_setup(struct device_struct *dev) {
+	char *buf;
+	int ioctl_param;
+
+	if(ioctl(dev->fd, SNDCTL_DSP_SYNC, NULL) == -1){
+		ERR("freebsd start: ioctl(SNDCTL_DSP_SYNC) failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	ioctl_param = AFMT_S16_LE;
+	if(ioctl(dev->fd, SNDCTL_DSP_SETFMT, &ioctl_param) == -1){
+		ERR("freebsd start: ioctl(SNDCTL_DSP_SETFMT) failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	ioctl_param = 1;
+	if(ioctl(dev->fd, SNDCTL_DSP_CHANNELS, &ioctl_param) == -1){
+		ERR("freebsd start: ioctl(SNDCTL_DSP_CHANNELS) failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	ioctl_param = 8000;
+	if(ioctl(dev->fd, SNDCTL_DSP_SPEED, &ioctl_param) == -1){
+		ERR("freebsd start: ioctl(SNDCTL_DSP_SPEED) failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	ioctl_param = AFMT_FULLDUPLEX;
+	if(ioctl(dev->fd, SNDCTL_DSP_SETDUPLEX, &ioctl_param) == -1){
+		ERR("freebsd start: ioctl(SNDCTL_DSP_SETDUPLEX) failed: %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* XXX workaround a NetBSD bug */
+	/*
+	buf = outbuf;
+	bzero(buf, 1);
+	freebsd_device_read(dev, buf, 1);
+	*/
+	
+	dev->delay = 0;
+	dev->delay += INTERNAL_DELAY; /* <-- fixme: delay detection is needed */
+
+	DBG("started\n");
+	return 0;
+}
+
+static int freebsd_stop (struct modem *m)
+{
+	struct device_struct *dev = m->dev_data;
+	DBG("freebsd stop...\n");
+	dev->started = 0;
+//	ioctl(dev->fd, AUDIO_DRAIN, NULL);
+	return 0;
+}
+
+static int freebsd_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
+{
+	/* TODO */
+	struct device_struct *dev = m->dev_data;
+	DBG("freebsd ioctl: cmd %x, arg %lx...\n",cmd,arg);
+	switch(cmd) {
+        case MDMCTL_CAPABILITIES:
+                return -EINVAL;
+        case MDMCTL_HOOKSTATE:
+                return 0;
+        case MDMCTL_CODECTYPE:
+                return CODEC_SILABS;
+        case MDMCTL_IODELAY:
+		DBG("delay = %d\n", dev->delay);
+		return dev->delay;
+#if 0
+	case MDMCTL_SPEED:
+		DBG("speed = %d\n", arg);
+		dev->info.play.sample_rate = dev->info.record.sample_rate = arg;
+		ioctl(dev->fd, AUDIO_SETINFO, &dev->info);
+		return 0;
+#endif
+	default:
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct modem_driver freebsd_modem_driver = {
+        .name = "freebsd modem driver",
+        .start = freebsd_start,
+        .stop = freebsd_stop,
+        .ioctl = freebsd_ioctl,
+};
+
+#endif /* !SUPPORT_FREEBSD */
+
+
+/*
  *    'driver' stuff
  *
  */
@@ -565,6 +1042,14 @@
 
 static char link_name[PATH_MAX];
 
+#ifdef __NetBSD__
+#define getpt() open("/dev/ptmx", O_RDWR)
+#endif
+
+#ifdef __FreeBSD__
+extern int getpt(void);
+#endif
+
 int create_pty(struct modem *m)
 {
 	struct termios termios;
@@ -715,18 +1200,33 @@
                         return ret;
                 }
 
-		if ( ret == 0 )
+		if ( ret == 0 ) {
+			DBG("select: timed out\n");
 			continue;
+		}
+		//DBG("select: didn't time out\n");
 
 		if(FD_ISSET(dev->fd, &eset)) {
 			unsigned stat;
-			//DBG("dev exception...\n");
+			DBG("dev exception...\n");
 #ifdef SUPPORT_ALSA
 			if(use_alsa) {
 				DBG("dev exception...\n");
 				continue;
 			}
 #endif
+#ifdef SUPPORT_NETBSD
+			if(use_netbsd) {
+				DBG("dev exception...\n");
+				continue;
+			}
+#endif
+#ifdef SUPPORT_FREEBSD
+			if(use_freebsd) {
+				DBG("dev exception...\n");
+				continue;
+			}
+#endif
 			ret = ioctl(dev->fd,MDMCTL_GETSTAT,&stat);
 			if(ret < 0) {
 				ERR("dev ioctl: %s\n",strerror(errno));
@@ -737,6 +1237,7 @@
 			continue;
 		}
 		if(FD_ISSET(dev->fd, &rset)) {
+			//DBG("FD_ISSET(dev->fd,&rset)\n");
 			count = device_read(dev,inbuf,sizeof(inbuf)/2);
 			if(count < 0) {
 				ERR("dev read: %s\n",strerror(errno));
@@ -789,6 +1290,7 @@
 			}
 		}
 		if(FD_ISSET(m->pty,&rset)) {
+			DBG("FD_ISSET(m->pty,&rset)\n");
 			/* check termios */
 			tcgetattr(m->pty,&termios);
 			if(memcmp(&termios,&m->termios,sizeof(termios))) {
@@ -886,6 +1388,7 @@
 	sprintf(path_name,"/var/lib/slmodem/data.%s",basename(dev_name));
 	datafile_load_info(path_name,&m->dsp_info);
 
+#if !defined(__NetBSD__) && !defined(__FreeBSD__)
 	if (need_realtime) {
 		struct sched_param prm;
 		if(mlockall(MCL_CURRENT|MCL_FUTURE)) {
@@ -897,6 +1400,7 @@
 		}
 		DBG("rt applyed: SCHED_FIFO, pri %d\n",prm.sched_priority);
 	}
+#endif
 
 	signal(SIGINT, mark_termination);
 	signal(SIGTERM, mark_termination);
@@ -952,6 +1456,24 @@
 		device_read = alsa_device_read;
 		device_write = alsa_device_write;
 		modem_driver = &alsa_modem_driver;
+	}
+#endif
+#ifdef SUPPORT_NETBSD
+	if(use_netbsd) {
+		device_setup = netbsd_device_setup;
+		device_release = netbsd_device_release;
+		device_read = netbsd_device_read;
+		device_write = netbsd_device_write;
+		modem_driver = &netbsd_modem_driver;
+	}
+#endif
+#ifdef SUPPORT_FREEBSD
+	if(use_freebsd) {
+		device_setup = freebsd_device_setup;
+		device_release = freebsd_device_release;
+		device_read = freebsd_device_read;
+		device_write = freebsd_device_write;
+		modem_driver = &freebsd_modem_driver;
 	}
 #endif
 
diff -ru slmodem-2.9.10.orig/modem/modem_test.c slmodem-2.9.10/modem/modem_test.c
--- slmodem-2.9.10.orig/modem/modem_test.c	Mon Mar  8 07:48:26 2004
+++ slmodem-2.9.10/modem/modem_test.c	Sat Jul  2 02:49:44 2005
@@ -61,6 +61,13 @@
 #define DBG(fmt,args...) if(modem_debug_level) \
                              fprintf(stderr, "main: " fmt , ##args );
 
+#ifdef __NetBSD__
+#define getpt() open("/dev/ptmx", O_RDWR)
+#endif
+
+#ifdef __FreeBSD__
+extern int getpt(void);
+#endif
 
 //#define SIMULATE_RING 1
 
