Comtrol Rocketport driver is severely hosed under 6.x-STABLE

Doug Ambrisko ambrisko at ambrisko.com
Thu Sep 7 11:21:55 PDT 2006


Karl Denninger writes:
| 
| There is a severe problem (or set of problmes) with the Comtrol Rocketport
| driver under FreeBSD 6.x, to the point that the driver is basically unusable.
| 
| The driver is returning duplicate input frames and otherwise misbehaving
| badly.  There were no problems under FreeBSD 5.x.
| 
| Does anyone know what has changed in the tty subsystem between 5.x and 6.x,
| or, alternatively if there is no update on this, is there a KNOWN WORKING
| PROPERLY multiport serial board under 6.x?
| 
| This has totally hosed a number of my field installations when they attempted
| to go from the 5.x operating environment to 6.x!
| 
| Thanks in advance....

Try this for 6.1 in /sys/dev/rp:

Index: rp.c
===================================================================
RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/rp/rp.c,v
retrieving revision 1.67.2.1
diff -u -p -r1.67.2.1 rp.c
--- rp.c	8 Nov 2005 15:35:27 -0000	1.67.2.1
+++ rp.c	7 Sep 2006 18:19:44 -0000
@@ -37,15 +37,18 @@ __FBSDID("$FreeBSD: src/sys/dev/rp/rp.c,
 /* 
  * rp.c - for RocketPort FreeBSD
  */
+#include <sys/cdefs.h>
 
 #include "opt_compat.h"
 
 #include <sys/param.h>
+#include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/fcntl.h>
 #include <sys/malloc.h>
 #include <sys/serial.h>
 #include <sys/tty.h>
+#include <sys/dkstat.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <machine/resource.h>
@@ -57,7 +60,7 @@ __FBSDID("$FreeBSD: src/sys/dev/rp/rp.c,
 #include <dev/rp/rpreg.h>
 #include <dev/rp/rpvar.h>
 
-static const char RocketPortVersion[] = "3.02";
+static const char RocketPortVersion[] = "1.0";
 
 static Byte_t RData[RDATASIZE] =
 {
@@ -116,6 +119,8 @@ Byte_t rp_sBitMapSetTbl[8] =
    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
 };
 
+int next_unit_number = 0;
+int num_devices_found = 0;
 /***************************************************************************
 Function: sReadAiopID
 Purpose:  Read the AIOP idenfication number directly from an AIOP.
@@ -587,6 +592,9 @@ static void rp_do_receive(struct rp_port
 	unsigned	int	CharNStat;
 	int	ToRecv, wRecv, ch, ttynocopy;
 
+	if (tp->t_state & TS_TBLOCK)
+		return;
+
 	ToRecv = sGetRxCnt(cp);
 	if(ToRecv == 0)
 		return;
@@ -615,7 +623,7 @@ static void rp_do_receive(struct rp_port
 			CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
 			ch = CharNStat & 0xff;
 
-			if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
+			if((CharNStat & STMBREAKH) || (CharNStat & STMFRAMEH))
 				ch |= TTY_FE;
 			else if (CharNStat & STMPARITYH)
 				ch |= TTY_PE;
@@ -645,6 +653,12 @@ static void rp_do_receive(struct rp_port
 			if ( ToRecv > RXFIFO_SIZE ) {
 				ToRecv = RXFIFO_SIZE;
 			}
+			if ((tp->t_rawq.c_cc + ToRecv > tp->t_ihiwat) &&
+			    ((tp->t_cflag & CRTS_IFLOW) ||
+			     (tp->t_iflag & IXOFF)) &&
+			    !(tp->t_state & TS_TBLOCK))
+				ttyblock(tp);
+
 			wRecv = ToRecv >> 1;
 			if ( wRecv ) {
 				rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
@@ -686,6 +700,7 @@ static void rp_handle_port(struct rp_por
 	IntMask = sGetChanIntID(cp);
 	IntMask = IntMask & rp->rp_intmask;
 	ChanStatus = sGetChanStatus(cp);
+	
 	if(IntMask & RXF_TRIG)
 		if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
 			rp_do_receive(rp, tp, cp, ChanStatus);
@@ -769,22 +784,23 @@ rp_attachcommon(CONTROLLER_T *ctlp, int 
 
 	unit = device_get_unit(ctlp->dev);
 
-	printf("RocketPort%d (Version %s) %d ports.\n", unit,
-		RocketPortVersion, num_ports);
+	printf("RocketPort%d = %d ports.\n", unit, num_ports);
 	rp_num_ports[unit] = num_ports;
 	callout_handle_init(&rp_callout_handle);
 
 	ctlp->rp = rp = (struct rp_port *)
-		malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
+		malloc(sizeof(struct rp_port) * (num_ports+1), M_TTYS, M_NOWAIT | M_ZERO);
 	if (rp == NULL) {
 		device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
 		retval = ENOMEM;
 		goto nogo;
 	}
-
+/*	else {
+		device_printf(ctlp->dev, "malloc'd rp_ports structures=%08x.\n", rp);
+	}*/
 	count = unit * 32;      /* board times max ports per card SG */
 
-	bzero(rp, sizeof(struct rp_port) * num_ports);
+	bzero(rp, sizeof(struct rp_port) * (num_ports+1));
 	oldspl = spltty();
 	rp_addr(unit) = rp;
 	splx(oldspl);
@@ -1016,9 +1032,10 @@ rpmodem(struct tty *tp, int sigon, int s
 	}
 	return (0);
 }
-
+#define B460800 460800
+#define B921600 921600
 static struct speedtab baud_table[] = {
-	{B0,	0},		{B50,	BRD50},		{B75,	BRD75},
+	{B0,	BRD0},		{B50,	BRD50},		{B75,	BRD75},
 	{B110,	BRD110}, 	{B134,	BRD134}, 	{B150,	BRD150},
 	{B200,	BRD200}, 	{B300,	BRD300}, 	{B600,	BRD600},
 	{B1200,	BRD1200},	{B1800,	BRD1800},	{B2400,	BRD2400},
@@ -1028,7 +1045,19 @@ static struct speedtab baud_table[] = {
 	{B115200, BRD115200},	{B230400, BRD230400},
 	{-1,	-1}
 };
-
+#ifdef DJA
+static struct speedtab ab_baud_table[] = {
+	{B0,	AB_BRD0},	{B50,	AB_BRD50},	{B75,	AB_BRD75},
+	{B110,	AB_BRD110}, 	{B134,	AB_BRD134}, 	{B150,	AB_BRD150},
+	{B200,	AB_BRD200}, 	{B300,	AB_BRD300}, 	{B600,	AB_BRD600},
+	{B1200,	AB_BRD1200},	{B1800,	AB_BRD1800},	{B2400,	AB_BRD2400},
+	{B4800,	AB_BRD4800},	{B9600,	AB_BRD9600},	{B19200, AB_BRD19200},
+	{B38400, AB_BRD38400},	{B7200,	AB_BRD7200},	{B14400, AB_BRD14400},
+	{B57600, AB_BRD57600},	{B76800, AB_BRD76800},	{B115200, AB_BRD115200},
+	{B230400,AB_BRD230400}, {B460800,AB_BRD460800}, {B921600, AB_BRD921600}, 
+	{-1,	-1}
+};
+#endif
 static int
 rpparam(tp, t)
 	struct tty *tp;
@@ -1042,7 +1071,6 @@ rpparam(tp, t)
 	int	devshift;
 #endif
 
-
 	rp = tp->t_sc;
 	cp = &rp->rp_channel;
 	oldspl = spltty();
@@ -1059,7 +1087,12 @@ rpparam(tp, t)
 	oflag = t->c_oflag;
 	lflag = t->c_lflag;
 
-	ospeed = ttspeedtab(t->c_ispeed, baud_table);
+#if DJA
+	if (cardIsRocketportPlus(ctl->dev))
+		ospeed = ttspeedtab(t->c_ispeed, ab_baud_table);
+	else
+#endif		
+		ospeed = ttspeedtab(t->c_ispeed, baud_table);
 	if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 		return(EINVAL);
 
Index: rp_isa.c
===================================================================
RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/rp/rp_isa.c,v
retrieving revision 1.7
diff -u -p -r1.7 rp_isa.c
--- rp_isa.c	6 Jan 2005 01:43:11 -0000	1.7
+++ rp_isa.c	7 Sep 2006 18:19:44 -0000
@@ -63,8 +63,8 @@ struct ISACONTROLLER_T {
 	int		MReg1IO;	/* offset1 of the Mudbac controller for this controller */
 	int		MReg2IO;	/* offset2 of the Mudbac controller for this controller */
 	int		MReg3IO;	/* offset3 of the Mudbac controller for this controller */
-	Byte_t		MReg2;
-	Byte_t		MReg3;
+	unsigned char	MReg2;
+	unsigned char	MReg3;
 };
 typedef struct ISACONTROLLER_T ISACONTROLLER_t;
 
@@ -140,6 +140,12 @@ static rp_aiop2rid_t rp_isa_aiop2rid;
 static rp_aiop2off_t rp_isa_aiop2off;
 static rp_ctlmask_t rp_isa_ctlmask;
 
+/*
+struct isa_driver rpdriver = {
+	rpprobe, rpattach, "rp" 
+	};
+*/
+
 static int
 rp_probe(device_t dev)
 {
@@ -149,6 +155,9 @@ rp_probe(device_t dev)
 	CONTROLLER_t *ctlp;
 	int retval;
 
+	if (num_devices_found >= 4)
+		return (ENXIO);
+
 	/*
 	 * We have no PnP RocketPort cards.
 	 * (At least according to LINT)
@@ -156,8 +165,8 @@ rp_probe(device_t dev)
 	if (isa_get_logicalid(dev) != 0)
 		return (ENXIO);
 
-	/* We need IO port resource to configure an ISA device. */
-	if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 0)
+	/* We need IO port resource to configure an ISA device.  */
+	if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0)
 		return (ENXIO);
 
 	unit = device_get_unit(dev);
@@ -176,20 +185,23 @@ rp_probe(device_t dev)
 
 	/* The IO ports of AIOPs for an ISA controller are discrete. */
 	ctlp->io_num = 1;
-	ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO);
-	ctlp->io = malloc(sizeof(*(ctlp->io)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO);
+	ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT/* | M_ZERO*/);
+	ctlp->io = malloc(sizeof(*(ctlp->io)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT/* | M_ZERO*/);
 	if (ctlp->io_rid == NULL || ctlp->io == NULL) {
 		device_printf(dev, "rp_attach: Out of memory.\n");
 		retval = ENOMEM;
 		goto nogo;
 	}
+	bzero(ctlp->io_rid, sizeof(*(ctlp->io_rid)) * MAX_AIOPS_PER_BOARD);
+	bzero(ctlp->io, sizeof(*(ctlp->io)) * MAX_AIOPS_PER_BOARD);
 
-	ctlp->bus_ctlp = malloc(sizeof(ISACONTROLLER_t) * 1, M_DEVBUF, M_NOWAIT | M_ZERO);
+	ctlp->bus_ctlp = malloc(sizeof(ISACONTROLLER_t) * 1, M_DEVBUF, M_NOWAIT/* | M_ZERO*/);
 	if (ctlp->bus_ctlp == NULL) {
 		device_printf(dev, "rp_attach: Out of memory.\n");
 		retval = ENOMEM;
 		goto nogo;
 	}
+	bzero(ctlp->bus_ctlp, sizeof(ISACONTROLLER_t) * 1);
 
 	ctlp->io_rid[0] = 0;
 	if (rp_controller != NULL) {
@@ -218,6 +230,7 @@ rp_probe(device_t dev)
 	if (rp_controller == NULL)
 		rp_controller = controller;
 	rp_nisadevs++;
+	num_devices_found++;
 
 	device_set_desc(dev, "RocketPort ISA");
 
@@ -416,7 +429,7 @@ sInitController(	CONTROLLER_T *CtlP,
 	CtlP->NumAiop = 0;
 	for(i=0; i < AiopNum; i++)
 	{
-		if (CtlP->io[i] == NULL) {
+		if (i > 0 /*CtlP->io[i] == NULL*/) {
 			CtlP->io_rid[i] = i;
 			aiop_base = rman_get_start(CtlP->io[0]) + 0x400 * i;
 			if (rp_nisadevs == 0)
Index: rp_pci.c
===================================================================
RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/rp/rp_pci.c,v
retrieving revision 1.11.2.1
diff -u -p -r1.11.2.1 rp_pci.c
--- rp_pci.c	14 Feb 2006 23:09:10 -0000	1.11.2.1
+++ rp_pci.c	7 Sep 2006 18:19:44 -0000
@@ -67,8 +67,19 @@ __FBSDID("$FreeBSD: src/sys/dev/rp/rp_pc
 #define RP_DEVICE_ID_4J		0x0007
 #define RP_DEVICE_ID_6M		0x000C
 #define RP_DEVICE_ID_4M		0x000D
-#define RP_DEVICE_ID_UPCI_32	0x0801
-#define RP_DEVICE_ID_UPCI_8O	0x0805
+#define RP_DEVICE_ID_PL4	0x000A
+#define RP_DEVICE_ID_PL8	0x000B
+#define RP_DEVICE_ID_PL2	0x000E
+#define RP_DEVICE_ID_U32	0x0801
+#define RP_DEVICE_ID_U8PL	0x0802
+#define RP_DEVICE_ID_U16	0x0803
+#define RP_DEVICE_ID_U8QO	0x0805
+#define RP_DEVICE_ID_UP8QO	0x080B
+#define RP_DEVICE_ID_UP2	0x080E
+#define RP_DEVICE_ID_UP2SMPTE	0x080F
+#define RP_DEVICE_ID_UP4J	0x0810
+#define RP_DEVICE_ID_UP8J	0x0811
+#define RP_DEVICE_ID_UP422QO	0x0812
 
 /**************************************************************************
   MUDBAC remapped for PCI
@@ -76,9 +87,20 @@ __FBSDID("$FreeBSD: src/sys/dev/rp/rp_pc
 
 #define _CFG_INT_PCI	0x40
 #define _PCI_INT_FUNC	0x3A
+#define _UPCI_INT_FUNC	0x4C		
 
 #define PCI_STROB	0x2000
+#define UPCI_STROB_C	0x0000
+#define UPCI_STROB_S	0x0001
+
 #define INTR_EN_PCI	0x0010
+#define INTR_EN_UPCI	0x0081
+
+#define _UPCI_GPIO	0x54
+#define _UPCI_QUAD_IN	0x0000
+#define _UPCI_OCTAL_IN	0x4000
+
+#define _UPCI_RING_IND 	0xc0          
 
 /***************************************************************************
 Function: sPCIControllerEOI
@@ -101,6 +123,40 @@ Return:   Byte_t: The controller interru
 */
 #define sPCIGetControllerIntStatus(CTLP) ((rp_readio2(CTLP, 0, _PCI_INT_FUNC) >> 8) & 0x1f)
 
+/***************************************************************************
+ *  Returns the state of RI. The following products have RI:  
+ *  UPCI 4/8 port, RP Plus 4/8 port, RP Plus 2 port 232/422.  
+ *  For all other devices, this function returns 0.
+ *
+ *  Returns:  1 if RI is set, else 0.
+ */
+int sGetChanRI(CHANNEL_T * ChP)
+{
+	CONTROLLER_t *CtlP = ChP->CtlP;
+	int ChanNum = ChP->ChanNum;
+	int RingInd;
+
+	switch (pci_get_device(CtlP->dev)) {
+	case RP_DEVICE_ID_U32:
+	case RP_DEVICE_ID_U8PL:
+	case RP_DEVICE_ID_U16:
+	case RP_DEVICE_ID_U8QO:
+		RingInd = !(rp_readio1(CtlP, 0, _UPCI_RING_IND) & rp_sBitMapSetTbl[ChanNum]);
+		break;
+	case RP_DEVICE_ID_PL4:
+	case RP_DEVICE_ID_PL8:
+	case RP_DEVICE_ID_PL2:
+	case RP_DEVICE_ID_UP8QO:
+	case RP_DEVICE_ID_UP2:
+		RingInd = rp_readch1(ChP, ((ChanNum * 2) + (_CHN_STAT0 + 8))) & DSR_ACT;
+		break;
+	default:
+		RingInd = 0;
+	}
+
+	return RingInd;
+}
+
 static devclass_t rp_devclass;
 
 static int rp_pciprobe(device_t dev);
@@ -115,7 +171,7 @@ static int sPCIInitController( CONTROLLE
 			       int IRQNum,
 			       Byte_t Frequency,
 			       int PeriodicOnly,
-			       int VendorDevice);
+			       uint16_t VendorDevice);
 static rp_aiop2rid_t rp_pci_aiop2rid;
 static rp_aiop2off_t rp_pci_aiop2off;
 static rp_ctlmask_t rp_pci_ctlmask;
@@ -129,12 +185,88 @@ static int
 rp_pciprobe(device_t dev)
 {
 	char *s;
+	uint16_t	VenDev;
 
-	s = NULL;
-	if (pci_get_vendor(dev) == RP_VENDOR_ID)
-		s = "RocketPort PCI";
+	if (num_devices_found >= 4)
+		return ENXIO;
 
+	s = NULL;
+	if (pci_get_vendor(dev) == RP_VENDOR_ID) {
+		VenDev = pci_get_device(dev);
+		switch( VenDev ) {
+		case RP_DEVICE_ID_4Q:
+			s = "RocketPort PCI Quad";
+			break;
+		case RP_DEVICE_ID_4J:
+			s = "RocketPort PCI 4J";
+			break;
+		case RP_DEVICE_ID_4M:
+			s = "RocketModem II PCI 4";
+			break;
+		case RP_DEVICE_ID_PL4:
+			s = "RocketPort Plus PCI Quad";
+			break;
+		case RP_DEVICE_ID_6M:
+			s = "RocketModem II PCI 6";
+			break;
+		case RP_DEVICE_ID_8O:
+			s = "RocketPort PCI Octa";
+			break;
+		case RP_DEVICE_ID_8J:
+			s = "RocketPort PCI 8J";
+			break;
+		case RP_DEVICE_ID_8I:
+			s = "RocketPort PCI 8";
+			break;
+		case RP_DEVICE_ID_U8PL:
+			s = "RocketPort Universal PCI 8 Low Profile";
+			break;
+		case RP_DEVICE_ID_U8QO:
+			s = "RocketPort Universal PCI Quad/Octa";
+			break;
+		case RP_DEVICE_ID_16I:
+			s = "RocketPort PCI 16";
+			break;
+		case RP_DEVICE_ID_U16:
+			s = "RocketPort Universal PCI 16";
+			break;
+		case RP_DEVICE_ID_32I:
+			s = "RocketPort PCI 32";
+			break;
+		case RP_DEVICE_ID_U32:
+			s = "RocketPort Universal PCI 32";
+			break;
+		case RP_DEVICE_ID_PL8:
+			s = "RocketPort Plus PCI Octa";
+			break;
+		case RP_DEVICE_ID_PL2:
+			s = "RocketPort Plus PCI 2";
+			break;
+		case RP_DEVICE_ID_UP8QO:
+			s = "RocketPort Plus Universal PCI Quad/Octa";
+			break;
+		case RP_DEVICE_ID_UP2:
+			s = "RocketPort Plus Universal PCI 2";
+			break;
+		case RP_DEVICE_ID_UP2SMPTE:
+			s = "RocketPort Plus Universal PCI 2 SMPTE";
+			break;
+		case RP_DEVICE_ID_UP4J:
+			s = "RocketPort Plus Universal PCI 4J";
+			break;
+		case RP_DEVICE_ID_UP8J:
+			s = "RocketPort Plus Universal PCI 8J";
+			break;
+		case RP_DEVICE_ID_UP422QO:
+			s = "RocketPort Plus Universal PCI 422 Quad/Octa";
+			break;
+		default:
+			s = NULL;
+			break;
+		}
+	}
 	if (s != NULL) {
+		num_devices_found++;
 		device_set_desc(dev, s);
 		return (BUS_PROBE_DEFAULT);
 	}
@@ -150,10 +282,14 @@ rp_pciattach(device_t dev)
 	CONTROLLER_t	*ctlp;
 	int	unit;
 	int	retval;
-	u_int32_t	stcmd;
-
+	uint32_t	stcmd;
+	uint16_t	VenDev;
+	
+	VenDev = pci_get_device(dev);
 	ctlp = device_get_softc(dev);
 	bzero(ctlp, sizeof(*ctlp));
+
+	ctlp->CtlID = CTLID_0001;	/* controller type 1 */
 	ctlp->dev = dev;
 	unit = device_get_unit(dev);
 	ctlp->aiop2rid = rp_pci_aiop2rid;
@@ -168,7 +304,11 @@ rp_pciattach(device_t dev)
 	}
 
 	/* The IO ports of AIOPs for a PCI controller are continuous. */
-	ctlp->io_num = 1;
+	if (cardIsUPCI(ctlp->dev))	/* if RocketPort UPCI with PLX chip */
+		ctlp->io_num = 2;	/*  then setup two base addresses */
+	else
+		ctlp->io_num = 1;	/*  or just setup one base address */
+
 	ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * ctlp->io_num, M_DEVBUF, M_NOWAIT | M_ZERO);
 	ctlp->io = malloc(sizeof(*(ctlp->io)) * ctlp->io_num, M_DEVBUF, M_NOWAIT | M_ZERO);
 	if (ctlp->io_rid == NULL || ctlp->io == NULL) {
@@ -179,15 +319,14 @@ rp_pciattach(device_t dev)
 
 	ctlp->bus_ctlp = NULL;
 
-	switch (pci_get_device(dev)) {
-	case RP_DEVICE_ID_UPCI_32:
-	case RP_DEVICE_ID_UPCI_8O:
-		ctlp->io_rid[0] = PCIR_BAR(2);
-		break;
-	default:
-		ctlp->io_rid[0] = PCIR_BAR(0);
-		break;
+	if (cardIsUPCI(ctlp->dev)) {    /* if RocketPort UPCI with PLX chip */
+		ctlp->io_rid[0] = 0x18; /*  then setup two base addresses */
+		ctlp->io_rid[1] = 0x14;
 	}
+	else {
+		ctlp->io_rid[0] = 0x10; /*  or just setup one base address */
+	}
+
 	ctlp->io[0] = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
 		&ctlp->io_rid[0], RF_ACTIVE);
 	if(ctlp->io[0] == NULL) {
@@ -195,7 +334,16 @@ rp_pciattach(device_t dev)
 		retval = ENXIO;
 		goto nogo;
 	}
-
+	if (cardIsUPCI(ctlp->dev)) {    /* if RocketPort UPCI with PLX chip */
+		ctlp->io[1] = bus_alloc_resource(dev, SYS_RES_IOPORT, &ctlp->io_rid[1], 0, ~0, 1, RF_ACTIVE);
+		/*device_printf(dev, "ioaddr (%x) mapping for RocketPort(UPCI) i
+s %08x.\n", ctlp->io_rid[1], ctlp->io[1]);*/
+		if(ctlp->io[1] == NULL) {
+		device_printf(dev, "ioaddr mapping failed for RocketPort (UPCI).\n");
+			retval = ENXIO;
+			goto nogo;
+		}
+	}
 	num_aiops = sPCIInitController(ctlp,
 				       MAX_AIOPS_PER_BOARD, 0,
 				       FREQ_DIS, 0, pci_get_device(dev));
@@ -265,20 +413,74 @@ rp_pcireleaseresource(CONTROLLER_t *ctlp
 	rp_releaseresource(ctlp);
 }
 
-static int
+static int 
 sPCIInitController( CONTROLLER_t *CtlP,
 		    int AiopNum,
 		    int IRQNum,
 		    Byte_t Frequency,
 		    int PeriodicOnly,
-		    int VendorDevice)
+		    uint16_t VendorDevice)
 {
-	int		i;
-
-	CtlP->CtlID = CTLID_0001;	/* controller release 1 */
-
-	sPCIControllerEOI(CtlP);
+	int		i, AiopChanCnt, gpio_dat;
 
+	if (cardIsUPCI(CtlP->dev))	/* if RocketPort UPCI with PLX chip */
+		rp_writeio2(CtlP, 1, _UPCI_INT_FUNC, 0x0000); /* disable ints */
+	else		
+		sPCIControllerEOI(CtlP);
+
+	switch( VendorDevice ) {
+	case RP_DEVICE_ID_4Q:
+	case RP_DEVICE_ID_4J:
+	case RP_DEVICE_ID_4M:
+	case RP_DEVICE_ID_PL4:
+	case RP_DEVICE_ID_UP4J:
+		AiopChanCnt = 4;
+		AiopNum = 1;
+		break;
+	case RP_DEVICE_ID_6M:
+		AiopChanCnt = 6;
+		AiopNum = 1;
+		break;
+	case RP_DEVICE_ID_8O:
+	case RP_DEVICE_ID_8J:
+	case RP_DEVICE_ID_8I:
+	case RP_DEVICE_ID_U8PL:
+	case RP_DEVICE_ID_U8QO:
+		AiopNum = 1;
+		AiopChanCnt = 8;
+		break;
+	case RP_DEVICE_ID_16I:
+	case RP_DEVICE_ID_U16:
+		AiopNum = 2;
+		AiopChanCnt = 8;
+		break;
+	case RP_DEVICE_ID_32I:
+	case RP_DEVICE_ID_U32:
+		AiopNum = 4;
+		AiopChanCnt = 8;
+		break;
+	case RP_DEVICE_ID_PL8:
+	case RP_DEVICE_ID_UP8J:
+	case RP_DEVICE_ID_UP8QO:
+	case RP_DEVICE_ID_UP422QO:
+		AiopNum = 2;
+		AiopChanCnt = 4;
+		break;
+	case RP_DEVICE_ID_PL2:
+	case RP_DEVICE_ID_UP2:
+	case RP_DEVICE_ID_UP2SMPTE:
+		AiopNum = 1;
+		AiopChanCnt = 2;
+		break;
+	default:
+		AiopNum = 1;
+#if notdef
+      		AiopChanCnt = 8;
+#else
+      		AiopChanCnt = sReadAiopNumChan(CtlP, 0);
+#endif /* notdef */
+			break;
+	}
 	/* Init AIOPs */
 	CtlP->NumAiop = 0;
 	for(i=0; i < AiopNum; i++)
@@ -290,39 +492,24 @@ sPCIInitController( CONTROLLER_t *CtlP,
 		{
 			break;				/* done looking for AIOPs */
 		}
-
-		switch( VendorDevice ) {
-		case RP_DEVICE_ID_4Q:
-		case RP_DEVICE_ID_4J:
-		case RP_DEVICE_ID_4M:
-      			CtlP->AiopNumChan[i] = 4;
-			break;
-		case RP_DEVICE_ID_6M:
-      			CtlP->AiopNumChan[i] = 6;
-			break;
-		case RP_DEVICE_ID_8O:
-		case RP_DEVICE_ID_8J:
-		case RP_DEVICE_ID_8I:
-		case RP_DEVICE_ID_16I:
-		case RP_DEVICE_ID_32I:
-      			CtlP->AiopNumChan[i] = 8;
-			break;
-		default:
-#if notdef
-      			CtlP->AiopNumChan[i] = 8;
-#else
-      			CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i);
-#endif /* notdef */
-			break;
-		}
+		if (VendorDevice == RP_DEVICE_ID_U8QO) {  /* if UPCI QUAD/OCTAL board */
+			gpio_dat = rp_readio2(CtlP, 1, _UPCI_GPIO); /* read GPIO reg */
+			if (!(gpio_dat & _UPCI_OCTAL_IN)) /*  if quad cable attached, */
+				AiopChanCnt = 4;	  /*    set for only four channels */
+		}			
+		CtlP->AiopNumChan[i] = AiopChanCnt;
 		/*device_printf(CtlP->dev, "%d channels.\n", CtlP->AiopNumChan[i]);*/
 		rp_writeaiop2(CtlP, i, _INDX_ADDR,_CLK_PRE);	/* clock prescaler */
-		/*device_printf(CtlP->dev, "configuring clock prescaler.\n");*/
-		rp_writeaiop1(CtlP, i, _INDX_DATA,CLOCK_PRESC);
-		/*device_printf(CtlP->dev, "configured clock prescaler.\n");*/
+		if (cardIsRocketportPlus(CtlP->dev)) {
+			rp_writeaiop1(CtlP, i, _INDX_DATA, AB_CLOCK_PRESC);
+			/*device_printf(CtlP->dev, "configured clock prescaler (%04x = %02x).\n",_CLK_PRE, AB_CLOCK_PRESC);*/
+		}			
+		else {
+			rp_writeaiop1(CtlP, i, _INDX_DATA, CLOCK_PRESC);
+			/*device_printf(CtlP->dev, "configured clock prescaler (%04x = %02x).\n",_CLK_PRE, CLOCK_PRESC);*/
+		}			
 		CtlP->NumAiop++;				/* bump count of AIOPs */
 	}
-
 	if(CtlP->NumAiop == 0)
 		return(-1);
 	else
@@ -355,7 +542,80 @@ rp_pci_aiop2off(int aiop, int offset)
 static unsigned char
 rp_pci_ctlmask(CONTROLLER_t *ctlp)
 {
-	return sPCIGetControllerIntStatus(ctlp);
+	int		cmsk;
+	unsigned char 	cret=0;
+	
+	if (cardIsUPCI(ctlp->dev)) {	/* if RocketPort UPCI with PLX chip */
+		cmsk = rp_readio2(ctlp, 1, _UPCI_GPIO);
+		if (cmsk & UINTSTAT0)	/* convert PLX int bits to AIOPIC int bits */
+			cret |= INTSTAT0;
+		if (cmsk & UINTSTAT1)
+			cret |= INTSTAT1;
+		if (cmsk & UINTSTAT2)
+			cret |= INTSTAT2;
+		if (cmsk & UINTSTAT3)
+			cret |= INTSTAT3;
+		cmsk = rp_readio2(ctlp, 1, _UPCI_INT_FUNC); /* get int active bit */
+		if (cmsk & UINTACT)
+			cret |= 0x10;
+		return cret;
+	}		
+	else {
+		return sPCIGetControllerIntStatus(ctlp);
+	}			
+}
+int 
+cardIsUPCI(device_t dev)
+{
+	uint16_t	VenDev;
+	int		upci_fnd;
+	
+	upci_fnd = FALSE;
+	VenDev = pci_get_device(dev);
+	switch( VenDev ) {
+	case RP_DEVICE_ID_U8PL:
+	case RP_DEVICE_ID_U8QO:
+	case RP_DEVICE_ID_U16:
+	case RP_DEVICE_ID_U32:
+	case RP_DEVICE_ID_UP8QO:
+	case RP_DEVICE_ID_UP2:
+	case RP_DEVICE_ID_UP2SMPTE:
+	case RP_DEVICE_ID_UP4J:
+	case RP_DEVICE_ID_UP8J:
+	case RP_DEVICE_ID_UP422QO:
+		upci_fnd = TRUE;			/* controller with PLX9030 chip */
+		break;
+	default:
+		upci_fnd = FALSE;
+		break;
+	}
+	return(upci_fnd);
+}
+int 
+cardIsRocketportPlus(device_t dev)
+{
+	uint16_t	VenDev;
+	int		rpl_fnd;
+	
+	rpl_fnd = FALSE;
+	VenDev = pci_get_device(dev);
+	switch( VenDev ) {
+	case RP_DEVICE_ID_PL4:
+	case RP_DEVICE_ID_PL8:
+	case RP_DEVICE_ID_PL2:
+	case RP_DEVICE_ID_UP8QO:
+	case RP_DEVICE_ID_UP2:
+	case RP_DEVICE_ID_UP2SMPTE:
+	case RP_DEVICE_ID_UP4J:
+	case RP_DEVICE_ID_UP8J:
+	case RP_DEVICE_ID_UP422QO:
+		rpl_fnd = TRUE;			/* RocketPort Plus board */
+		break;
+	default:
+		rpl_fnd = FALSE;
+		break;
+	}
+	return(rpl_fnd);
 }
 
 static device_method_t rp_pcimethods[] = {
Index: rpreg.h
===================================================================
RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/rp/rpreg.h,v
retrieving revision 1.7
diff -u -p -r1.7 rpreg.h
--- rpreg.h	6 Jan 2005 01:43:11 -0000	1.7
+++ rpreg.h	7 Sep 2006 18:19:44 -0000
@@ -133,6 +133,8 @@ typedef unsigned int DWordIO_t;
 /* Controller ID numbers */
 #define CTLID_NULL  -1		    /* no controller exists */
 #define CTLID_0001  0x0001	    /* controller release 1 */
+#define CTLID_0002  0x0002	    /* controller with PLX9030 chip */
+#define CTLID_0003  0x0003	    /* Rocketport Plus board */
 
 /* AIOP ID numbers, identifies AIOP type implementing channel */
 #define AIOPID_NULL -1		    /* no AIOP or channel exists */
@@ -213,8 +215,11 @@ Channel Register Offsets - Indexed - Int
 #define _BAUD	    0xFF4    /* Baud Rate		       16  Write */
 #define _CLK_PRE    0xFF6    /* Clock Prescaler 		8  Write */
 
+/************************************************************************
+        Baud rate divisors using mod 9 clock prescaler and 36.873 clock
+************************************************************************/
 #define CLOCK_PRESC 0x19	  /* mod 9 (divide by 10) prescale */
-
+#define BRD0              3     /* tps remapped for 57.6KB */
 #define BRD50		  4607
 #define BRD75		  3071
 #define BRD110		  2094
@@ -238,6 +243,35 @@ Channel Register Offsets - Indexed - Int
 #define BRD76800	  2
 #define BRD115200	  1
 #define BRD230400	  0
+/************************************************************************
+        Baud rate divisors using mod 2 clock prescaler and 44.2368 clock
+************************************************************************/
+#define AB_CLOCK_PRESC 0x12          /* mod 2 prescale */
+#define AB_BRD0		     3     /* tps remapped for 57.6KB */
+#define AB_BRD50             18431
+#define AB_BRD75             12287
+#define AB_BRD110            8377
+#define AB_BRD134            6852 
+#define AB_BRD150            6143
+#define AB_BRD200            4607
+#define AB_BRD300            3071
+#define AB_BRD600            1535
+#define AB_BRD1200           767
+#define AB_BRD1800           511
+#define AB_BRD2400           383
+#define AB_BRD4800           191
+#define AB_BRD7200           127
+#define AB_BRD9600           95
+#define AB_BRD14400          63
+#define AB_BRD19200          47
+#define AB_BRD28800          31
+#define AB_BRD38400          23
+#define AB_BRD57600          15
+#define AB_BRD76800          11
+#define AB_BRD115200         7
+#define AB_BRD230400         3
+#define AB_BRD460800         2
+#define AB_BRD921600         0
 
 #define STMBREAK   0x08        /* BREAK */
 #define STMFRAME   0x04        /* framing error */
@@ -316,6 +350,12 @@ Channel Register Offsets - Indexed - Int
 #define INTSTAT2  0x04	      /* AIOP 2 interrupt status */
 #define INTSTAT3  0x08	      /* AIOP 3 interrupt status */
 
+#define UINTACT   0x04	      /* UPCI AIOP Interrupt active */
+#define UINTSTAT0 0x04	      /* UPCI AIOP 0 interrupt status */
+#define UINTSTAT1 0x20	      /* UPCI AIOP 1 interrupt status */
+#define UINTSTAT2 0x100	      /* UPCI AIOP 2 interrupt status */
+#define UINTSTAT3 0x800       /* UPCI AIOP 3 interrupt status */
+
 #define INTR_EN   0x08	      /* allow interrupts to host */
 #define INT_STROB 0x04	      /* strobe and clear interrupt line (EOI) */
 
@@ -1004,7 +1044,12 @@ void sEnInterrupts(CHANNEL_T *ChP,Word_t
 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags);
 int rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports);
 void rp_releaseresource(CONTROLLER_t *ctlp);
+int cardIsUPCI(device_t dev);
+int cardIsRocketportPlus(device_t dev);
+int sGetChanRI(CHANNEL_T * ChP);
 void rp_untimeout(void);
+extern int next_unit_number;
+extern int num_devices_found;
 
 #ifndef ROCKET_C
 extern Byte_t R[RDATASIZE];
Index: rpvar.h
===================================================================
RCS file: /usr/local/cvsroot/freebsd/src/sys/dev/rp/rpvar.h,v
retrieving revision 1.8
diff -u -p -r1.8 rpvar.h
--- rpvar.h	6 Jan 2005 01:43:11 -0000	1.8
+++ rpvar.h	7 Sep 2006 18:19:44 -0000
@@ -63,8 +63,8 @@ struct rp_port {
 	int			rp_xmit_stopped:1;
 	CONTROLLER_t *		rp_ctlp;
 	CHANNEL_t		rp_channel;
-	unsigned short		TxBuf[TXFIFO_SIZE/2 +1];
-	unsigned short		RxBuf[RXFIFO_SIZE/2 +1];
+	unsigned short		TxBuf[TXFIFO_SIZE/2 + 1];
+	unsigned short		RxBuf[RXFIFO_SIZE/2 + 1];
 };
 
 /* Actually not used */

This works for me and supports more HW.

Doug A.


More information about the freebsd-stable mailing list