summaryrefslogtreecommitdiffstats
path: root/sys/dev/sio
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sio')
-rw-r--r--sys/dev/sio/sio.c166
1 files changed, 164 insertions, 2 deletions
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c
index 99f913f..70eb097 100644
--- a/sys/dev/sio/sio.c
+++ b/sys/dev/sio/sio.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
- * $Id: sio.c,v 1.50 1994/08/23 07:52:23 paul Exp $
+ * $Id: sio.c,v 1.51 1994/08/25 10:15:28 bde Exp $
*/
#include "sio.h"
@@ -278,6 +278,10 @@ static void comstart __P((struct tty *tp));
static timeout_t comwakeup;
static int tiocm_xxx2mcr __P((int tiocm_xxx));
+#ifdef DSI_SOFT_MODEM
+static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr));
+#endif /* DSI_SOFT_MODEM */
+
/* table and macro for fast conversion from a unit number to its com struct */
static struct com_s *p_com_addr[NSIO];
#define com_addr(unit) (p_com_addr[unit])
@@ -592,6 +596,14 @@ sioattach(isdp)
/* attempt to determine UART type */
printf("sio%d: type", unit);
+
+#ifdef DSI_SOFT_MODEM
+ if((inb(iobase+7) ^ inb(iobase+7)) & 0x80) {
+ printf(" Digicom Systems, Inc. SoftModem");
+ goto determined_type;
+ }
+#endif /* DSI_SOFT_MODEM */
+
#ifdef COM_MULTIPORT
if (!COM_ISMULTIPORT(isdp))
#endif
@@ -931,6 +943,7 @@ siowrite(dev, uio, flag)
mynor = minor(dev);
if (mynor & CONTROL_MASK)
return (ENODEV);
+
unit = MINOR_TO_UNIT(mynor);
tp = com_addr(unit)->tp;
/*
@@ -1156,6 +1169,7 @@ sioioctl(dev, cmd, data, flag, p)
mynor = minor(dev);
com = com_addr(MINOR_TO_UNIT(mynor));
+ iobase = com->iobase;
if (mynor & CONTROL_MASK) {
struct termios *ct;
@@ -1185,6 +1199,34 @@ sioioctl(dev, cmd, data, flag, p)
case TIOCGWINSZ:
bzero(data, sizeof(struct winsize));
return (0);
+#ifdef DSI_SOFT_MODEM
+ /*
+ * Download micro-code to Digicom modem.
+ */
+ case TIOCDSIMICROCODE:
+ {
+ u_long l;
+ u_char *p,*pi;
+
+ pi = (u_char*)(*(caddr_t*)data);
+ error = copyin(pi,&l,sizeof l);
+ if(error)
+ {return error;};
+ pi += sizeof l;
+
+ p = malloc(l,M_TEMP,M_NOWAIT);
+ if(!p)
+ {return ENOBUFS;}
+ error = copyin(pi,p,l);
+ if(error)
+ {free(p,M_TEMP); return error;};
+ if(error = LoadSoftModem(
+ MINOR_TO_UNIT(mynor),iobase,l,p))
+ {free(p,M_TEMP); return error;}
+ free(p,M_TEMP);
+ return(0);
+ }
+#endif /* DSI_SOFT_MODEM */
default:
return (ENOTTY);
}
@@ -1218,7 +1260,6 @@ sioioctl(dev, cmd, data, flag, p)
error = ttioctl(tp, cmd, data, flag);
if (error >= 0)
return (error);
- iobase = com->iobase;
s = spltty();
switch (cmd) {
case TIOCSBRK:
@@ -1954,4 +1995,125 @@ siocnputc(dev, c)
splx(s);
}
+#ifdef DSI_SOFT_MODEM
+/*
+ * The magic code to download microcode to a "Connection 14.4+Fax"
+ * modem from Digicom Systems Inc. Very magic.
+ */
+
+#define DSI_ERROR(str) { ptr = str; goto error; }
+static int
+LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
+{
+ int int_c,int_k;
+ int data_0188, data_0187;
+
+ /*
+ * First see if it is a DSI SoftModem
+ */
+ if(!((inb(base_io+7) ^ inb(base_io+7) & 0x80)))
+ return ENODEV;
+
+ data_0188 = inb(base_io+4);
+ data_0187 = inb(base_io+3);
+ outb(base_io+3,0x80);
+ outb(base_io+4,0x0C);
+ outb(base_io+0,0x31);
+ outb(base_io+1,0x8C);
+ outb(base_io+7,0x10);
+ outb(base_io+7,0x19);
+
+ if(0x18 != (inb(base_io+7) & 0x1A))
+ DSI_ERROR("dsp bus not granted");
+
+ if(0x01 != (inb(base_io+7) & 0x01)) {
+ outb(base_io+7,0x18);
+ outb(base_io+7,0x19);
+ if(0x01 != (inb(base_io+7) & 0x01))
+ DSI_ERROR("program mem not granted");
+ }
+
+ int_c = 0;
+
+ while(1) {
+ if(int_c >= 7 || size <= 0x1800)
+ break;
+
+ for(int_k = 0 ; int_k < 0x800; int_k++) {
+ outb(base_io+0,*ptr++);
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,*ptr++);
+ }
+
+ size -= 0x1800;
+ int_c++;
+ }
+
+ if(size > 0x1800) {
+ outb(base_io+7,0x18);
+ outb(base_io+7,0x19);
+ if(0x00 != (inb(base_io+7) & 0x01))
+ DSI_ERROR("program data not granted");
+
+ for(int_k = 0 ; int_k < 0x800; int_k++) {
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,0);
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,*ptr++);
+ }
+
+ size -= 0x1800;
+
+ while(size > 0x1800) {
+ for(int_k = 0 ; int_k < 0xC00; int_k++) {
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,*ptr++);
+ }
+ size -= 0x1800;
+ }
+
+ if(size < 0x1800) {
+ for(int_k=0;int_k<size/2;int_k++) {
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,*ptr++);
+ }
+ }
+
+ } else if (size > 0) {
+ if(int_c == 7) {
+ outb(base_io+7,0x18);
+ outb(base_io+7,0x19);
+ if(0x00 != (inb(base_io+7) & 0x01))
+ DSI_ERROR("program data not granted");
+ for(int_k = 0 ; int_k < size/3; int_k++) {
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,0);
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,*ptr++);
+ }
+ } else {
+ for(int_k = 0 ; int_k < size/3; int_k++) {
+ outb(base_io+0,*ptr++);
+ outb(base_io+1,*ptr++);
+ outb(base_io+2,*ptr++);
+ }
+ }
+ }
+ outb(base_io+7,0x11);
+ outb(base_io+7,3);
+
+ outb(base_io+4,data_0188 & 0xfb);
+
+ outb(base_io+3,data_0187);
+
+ return 0;
+error:
+ printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",ptr);
+ outb(base_io+7,0x00); \
+ outb(base_io+3,data_0187); \
+ outb(base_io+4,data_0188); \
+ return EIO;
+}
+#endif /* DSI_SOFT_MODEM */
+
#endif /* NSIO > 0 */
OpenPOWER on IntegriCloud