Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 Feb 1999 07:58:35 +0100
From:      Matthias Apitz <guru@Sisis.de>
To:        Steve Emmert <steve@emmert.com>
Cc:        freebsd-mobile@FreeBSD.ORG, Nate Williams <nate@mt.sri.com>
Subject:   Re: O2 Micro OZ6832/6833 pci-cardbus controller
Message-ID:  <19990215075835.40475@sisis.de>
In-Reply-To: <Pine.BSF.4.05.9902130836190.376-100000@free.emmert.com>; from Steve Emmert on Sat, Feb 13, 1999 at 10:48:37AM -0800
References:  <Pine.BSF.4.05.9902130836190.376-100000@free.emmert.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii

On Sat, Feb 13, 1999 at 10:48:37AM -0800, Steve Emmert wrote:
> I have recently purchased an IBM Thinkpad that has a O2 Micro-
> OZ6832/6833 pci-cardbus controller. I see from the list archives
> that there is a patch out there to get this controller working.
> Could some kind person E-mail me the patch or direct me to a
> site where i could download it. My Thinkpad is running 3.1-
> BETA if that makes a difference.

Hi Steve,

attached below is my patch for O2Micro's OZ6832 CardBus controller.
The diff is against 2.2.7 and I don't know if this will work with
3.1 and your 6833 too. Please check it out and let me and the list
know. There is also a trick or hack used to identify the chip. Check
the comments for details and it may occur that this test will
fail for your chip anyway -- so play with it / change it. A better
solution should be worked out...

Hope it helps.

	matthias
-- 
firm: matthias.apitz@sisis.de [voc:+49 89 61308 351, fax: +49 89 61308 188]
priv: guru@thias.muc.de
 WWW: http://www.sisis.de/~guru/

Give me UNIX or give me a typewriter.

--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="OZ6832.diff"

*** pci/pcic_p.h.orig	Sat Feb  7 21:38:58 1998
--- pci/pcic_p.h	Thu Apr 16 08:00:14 1998
***************
*** 35,40 ****
--- 35,41 ----
  #define	PCI_DEVICE_ID_PCIC_O2MICRO	0x673A1217ul
  #define	PCI_DEVICE_ID_PCIC_TI1130	0xAC12104Cul
  #define	PCI_DEVICE_ID_PCIC_TI1131	0xAC15104Cul
+ #define	PCI_DEVICE_ID_PCIC_OZ6832	0x68321217ul
  
  /* CL-PD6832 CardBus defines */
  #define	CLPD6832_IO_BASE0		0x002c
***************
*** 52,54 ****
--- 53,73 ----
  #define	CLPD6832_NUM_REGS		2
  
  /* End of CL-PD6832 defines */
+ 
+ /* O2Micro OZ6832 CardBus defines */
+ /* matthias.apitz@sisis.de        */
+ 
+ #define	OZ6832_IO_BASE0			0x002c
+ #define	OZ6832_IO_LIMIT0		0x0030
+ #define	OZ6832_IO_BASE1			0x0034
+ #define	OZ6832_IO_LIMIT1		0x0038
+ #define	OZ6832_BRIDGE_CONTROL		0x003c
+ #define	OZ6832_LEGACY_16BIT_IOADDR	0x0044
+ 
+ /* O2Micro OZ6832 Configuration constants */
+ #define	OZ6832_BCR_ISA_IRQ		0x00800000
+ #define	OZ6832_COMMAND_DEFAULTS		0x00000007
+ 
+ #define	OZ6832_NUM_REGS			2
+ 
+ /* End of O2Micro OZ6832 CardBus defines */
*** pci/pcic_p.c.orig	Sat Feb  7 21:42:29 1998
--- pci/pcic_p.c	Fri Apr 17 07:47:37 1998
***************
*** 29,34 ****
--- 29,40 ----
   * $Id: pcic_p.c,v 1.4.2.2 1998/02/07 20:42:29 nate Exp $
   */
  
+  /*
+   * modified for O2Micro's OZ6832 PCI to CardBus controller
+   * by Matthias Apitz <matthias.apitz@sisis.de>
+   * April, 1998
+   */
+ 
  #include "pci.h"
  #if NPCI > 0
  
***************
*** 48,53 ****
--- 54,61 ----
  static void  pcic_pci_attach(pcici_t, int);
  
  static void  pd6832_legacy_init(pcici_t tag, int unit);
+ static void  oz6832_legacy_init(pcici_t tag, int unit);
+ static void  pcic_pci_printConfig(pcici_t tag, char *s);
  
  static struct pci_device pcic_pci_driver = {
  	"pcic",
***************
*** 66,71 ****
--- 74,80 ----
  static char *
  pcic_pci_probe(pcici_t tag, pcidi_t type)
  {
+ 
  	switch (type) {
  	case PCI_DEVICE_ID_PCIC_CLPD6729:
  		return ("Cirrus Logic PD6729/6730 PC-Card Controller");
***************
*** 75,80 ****
--- 84,91 ----
  		return ("TI 1130 PCMCIA/CardBus Bridge");
  	case PCI_DEVICE_ID_PCIC_TI1131:
  		return ("TI 1131 PCI to PCMCIA/CardBus bridge");
+ 	case PCI_DEVICE_ID_PCIC_OZ6832:
+ 		return ("O2Micro OZ6832 CardBus bridge");
  	default:
  		break;
  	}
***************
*** 84,90 ****
  
  /*
   * General PCI based card dispatch routine.  Right now
!  * it only understands the CL-PD6832.
   */
  static void
  pcic_pci_attach(pcici_t config_id, int unit)
--- 95,103 ----
  
  /*
   * General PCI based card dispatch routine.  Right now
!  * it only understands the follwoing chips:
!  * Cirrus Logic PD6832
!  * O2Micro OZ6832
   */
  static void
  pcic_pci_attach(pcici_t config_id, int unit)
***************
*** 97,102 ****
--- 110,124 ----
  	case PCI_DEVICE_ID_PCIC_CLPD6832:
  		pd6832_legacy_init(config_id, unit);
  		break;
+ 	case PCI_DEVICE_ID_PCIC_OZ6832:
+ 		oz6832_legacy_init(config_id, unit);
+ 		/*
+ 		 * no way to print the CardBus soccket regs and
+ 		 * ExCA regs here for the moment -- we skip the rest
+ 		 * of the function;
+ 		 */
+ 		return;
+ 		break;
  	}
  
  	if (bootverbose) { 		
***************
*** 192,196 ****
--- 214,306 ----
  	if (bootverbose)
  		printf("CardBus: Legacy PC-card 16bit I/O address [0x%x]\n",
  		       io_port);
+ }
+ 
+ /*
+  * Set up the O2Mirco OZ6832 to look like a ISA based PCMCIA chip (a
+  * PD672X).  This routine is called once per PCMCIA socket.
+  */
+ static void
+ oz6832_legacy_init(pcici_t tag, int unit)
+ {
+ 	u_long bcr; 		/* to set interrupts */
+ 	u_short io_port;	/* the io_port to map this slot on */
+ 	static int num6832 = 0; /* The number of 6832s initialized */
+ 
+ 	/*
+ 	 * Some BIOS leave the legacy address uninitialized.  This
+ 	 * insures that the PD6832 puts itself where the driver will
+ 	 * look.  We assume that multiple 6832's should be laid out
+ 	 * sequentially.  We only initialize the first socket's legacy port,
+ 	 * the other is a dummy.
+ 	 */
+ 	if (bootverbose)
+ 		pcic_pci_printConfig(tag, "as got from BIOS");
+ 
+ 	io_port = PCIC_INDEX_0 + num6832 * OZ6832_NUM_REGS;
+ 	if (unit == 0)	{
+ 	    pci_conf_write(tag, OZ6832_LEGACY_16BIT_IOADDR,
+ 		           io_port & ~PCI_MAP_IO);
+ 	}
+ 
+ 	/*
+ 	 * I think this should be a call to pci_map_port, but that
+ 	 * routine won't map regiaters above 0x28, and the register we
+ 	 * need to map is 0x44.
+ 	 */
+ 	 
+ 	io_port = pci_conf_read(tag, OZ6832_LEGACY_16BIT_IOADDR)
+ 	    & ~PCI_MAP_IO;
+ 
+ 	/*
+ 	 * Set default operating mode (I/O port space) and allocate
+ 	 * this socket to the current unit.
+ 	 */
+ 	 
+ 	pci_conf_write(tag, PCI_COMMAND_STATUS_REG, OZ6832_COMMAND_DEFAULTS);
+ 
+ 	/*
+ 	 * Set up the card inserted/card removed interrupts to come
+ 	 * through the isa IRQ.
+ 	 */
+ 	bcr = pci_conf_read(tag, OZ6832_BRIDGE_CONTROL);
+ 	bcr |= OZ6832_BCR_ISA_IRQ;
+ 	pci_conf_write(tag, OZ6832_BRIDGE_CONTROL, bcr);
+ 
+ 	/* After initializing 2 sockets, the chip is fully configured */
+ 	if (unit == 1)
+ 		num6832++;
+ 
+ 	if (bootverbose)	{
+ 		pcic_pci_printConfig(tag, "after oz6832_legacy_init");
+ 		printf("CardBus: Legacy PC-card 16bit I/O address [0x%x]\n",
+ 		       io_port);
+ 	}
+ }
+ 
+ /*
+  * Dump the PCI Config Space
+  */
+ static void
+ pcic_pci_printConfig(pcici_t config_id, char *s)
+ {
+ 	int i, j;
+ 	u_char *p;
+ 	u_long *pl;
+ 
+ 	printf("PCI Config space %s:\n", s);
+ 	for (j = 0; j < 0x98; j += 16) {
+ 		printf("%02x: ", j);
+ 		for (i = 0; i < 16; i += 4)
+ 			printf(" %08x", pci_conf_read(config_id, i+j));
+ 		printf("\n");
+ 	}
+ 	/*
+ 	 * the rest of the function is nonsense at the moment
+ 	 * because we have no idea how to access the
+ 	 * Cardbus Socket regs because the addr in 0x10 is NULL
+ 	 */
+ 	printf("Cardbus Socket registers not available.\n");
+ 
  }
  #endif /* NPCI > 0 */
*** pccard/i82365.h.orig	Thu Oct 23 20:44:06 1997
--- pccard/i82365.h	Fri Apr 17 17:00:17 1998
***************
*** 45,50 ****
--- 45,51 ----
  #define	PCIC_IBM_KING	9		/* IBM KING PCMCIA Controller */
  #define	PCIC_PC98	10		/* NEC PC98 PCMCIA Controller */
  #define	PCIC_TI1130	11		/* TI PCI1130 CardBus */
+ #define	PCIC_OZ6832	12		/* O2Micro 6832 CardBus */
  
  /*
   *	Address of the controllers. Each controller can manage
***************
*** 87,92 ****
--- 88,95 ----
  #define	PCIC_TIME_CMD1		0x3e
  #define	PCIC_TIME_RECOV1	0x3f
  
+ #define	PCIC_O2MICRO_MCTRL_B	0x39	/* O2Micro Mode Control Register B */
+ 
  #define	PCIC_SLOT_SIZE	0x40	/* Size of register set for one slot */
  
  /* Now register bits, ordered by reg # */
***************
*** 94,99 ****
--- 97,103 ----
  /* For Identification and Revision (PCIC_ID_REV) */
  #define PCIC_INTEL0	0x82	/* Intel 82365SL Rev. 0; Both Memory and I/O */
  #define PCIC_INTEL1	0x83	/* Intel 82365SL Rev. 1; Both Memory and I/O */
+ #define PCIC_O2MICRO	0x87	/* O2Micro OZ6832; Both Memory and I/O */
  #define PCIC_IBM1	0x88	/* IBM PCIC clone; Both Memory and I/O */
  #define PCIC_IBM2	0x89	/* IBM PCIC clone; Both Memory and I/O */
  #define PCIC_IBM3	0x8a	/* IBM KING PCIC clone; Both Memory and I/O */
*** pccard/pcic.c.orig	Sat Nov 15 15:11:34 1997
--- pccard/pcic.c	Sat Apr 18 07:58:27 1998
***************
*** 33,38 ****
--- 33,45 ----
   * by Noriyuki Hosobuchi <yj8n-hsbc@asahi-net.or.jp>
   */
  
+  /*
+   * modified for O2Micro's OZ6832 PCI to CardBus controller
+   * by Matthias Apitz <matthias.apitz@sisis.de>
+   * April, 1998
+   */
+ 
+ 
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/kernel.h>
***************
*** 90,95 ****
--- 97,103 ----
  static unsigned		pcic_imask;
  static struct slot_ctrl cinfo;
  
+ static void dump_register_table(struct pcic_slot *sp, char *s);
  
  /*
   *	Internal inline functions for accessing the PCIC.
***************
*** 538,543 ****
--- 546,562 ----
   *	of slot 1.  Assume it's the only PCIC whose vendor ID is 0x84,
   *	contact Nate Williams <nate@FreeBSD.org> if incorrect.
   */
+ 
+ /*
+  *	O2Micro's OZ6832 comes along with a vendor ID 0x82 and
+  *	mostly works like an Intel clone. You may detect it as
+  *	an OZ6832 by switching on the O2Micro-mode (see below)
+  *	and see if the vendor ID changes to 0x87, contact Matthias
+  *	Apitz <guru@sisis.de> if this doesn't work for you. The
+  *	PCIC can't steer out interupts for card status changes, only
+  *	for I/O the steering does work and this also stops to
+  *	work if you enable irq steering for status changes. sigh.
+  */
  int
  pcic_probe(void)
  {
***************
*** 546,551 ****
--- 565,572 ----
  	struct slot *slt;
  	struct pcic_slot *sp;
  	unsigned char c;
+ 	unsigned char o2mode;
+ 	unsigned char save;
  	static int maybe_vlsi = 0;
  
  	/* Determine the list of free interrupts */
***************
*** 610,616 ****
--- 631,668 ----
  		 *	82365 or clones.
  		 */
  		case 0x82:
+ 			/* 
+ 			 * first let's look for an O2Micro OZ6832 CardBus
+ 			 * controller...
+ 			 *
+ 			 * setting the two bits [1:0] in the register
+ 			 * "O2Micro control B" at offset 39h to the value
+ 			 * 0x02 should switch the PCIC_ID_REV from 0x82
+ 			 * to 0x87 (PCIC_O2MICRO)
+ 			 */
+ #ifdef PCIC_DEBUG
+ 			dump_register_table(sp, "pcic_probe() for O2Micro");
+ #endif
+ 			save = sp->getb(sp, PCIC_O2MICRO_MCTRL_B);
+ 			clrb(sp, PCIC_O2MICRO_MCTRL_B, 0x01);
+ 			setb(sp, PCIC_O2MICRO_MCTRL_B, 0x02);
+ 			o2mode = sp->getb(sp, PCIC_ID_REV);
+ 			/* restore the old value and see what o2mode has ... */
+ 			sp->putb(sp, PCIC_O2MICRO_MCTRL_B, save);
+ 			if(o2mode == PCIC_O2MICRO)	{
+ 				printf("pcic: found an O2Micro OZ6832 CardBus controller\n");
+ 				printf("pcic: PCIC_ID_REV was switchable to 0x%x\n", o2mode);
+ 				sp->controller = PCIC_OZ6832;
+ 				sp->revision = c & 1;
+ 				break;
+ 			}
+ 			/*
+ 			 * ... fall through if not an OZ6832
+ 		 	 */
  		case 0x83:
+ #ifdef PCIC_DEBUG
+ 			dump_register_table(sp, "pcic_probe() for 82365 clone");
+ #endif
  			sp->controller = PCIC_I82365;
  			sp->revision = c & 1;
  			/*
***************
*** 670,675 ****
--- 722,730 ----
  			}
  		}
  		switch(sp->controller) {
+ 		case PCIC_OZ6832:
+ 			cinfo.name = "O2Micro OZ6832";
+ 			break;
  		case PCIC_I82365:
  			cinfo.name = "Intel 82365";
  			break;
***************
*** 703,712 ****
  		}
  #ifndef	PCIC_NOCLRREGS
  		/*
! 		 *	clear out the registers.
  		 */
! 		for (i = 2; i < 0x40; i++)
! 			sp->putb(sp, i, 0);
  #endif	/* PCIC_NOCLRREGS */
  		/*
  		 *	OK it seems we have a PCIC or lookalike.
--- 758,770 ----
  		}
  #ifndef	PCIC_NOCLRREGS
  		/*
! 		 *	clear out the registers if no O2Micro chip
  		 */
! 		if(sp->controller != PCIC_OZ6832) {
! 			printf("pcic: zero out for all ExCA regs\n");
! 			for (i = 2; i < 0x40; i++)
! 				sp->putb(sp, i, 0);
! 		}
  #endif	/* PCIC_NOCLRREGS */
  		/*
  		 *	OK it seems we have a PCIC or lookalike.
***************
*** 754,763 ****
  			pccard_event(sp->slt, card_inserted);
  		}
  		/*
! 		 *	Assign IRQ for slot changes
  		 */
! 		if (pcic_irq > 0)
! 			sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);
  	}
  #ifdef	PC98
  	if (validslots == 0) {
--- 812,838 ----
  			pccard_event(sp->slt, card_inserted);
  		}
  		/*
! 		 * Assign IRQ for slot changes
! 		 * 
! 		 * the folks @ o2micro.com say: we can't generate
! 		 * ISA IRQ's for status changes in OZ6832 ...
! 		 * for the moment we simple set PCIC_STAT_INT to 0xf
! 		 * and rely on the polling in the driver;
  		 */
! 		if (pcic_irq > 0)	{
! 			if(sp->controller == PCIC_OZ6832)	{
! 				printf("pcic: OZ6832 can't steer irqs for slot changes -- irq unused\n");
! 				sp->putb(sp, PCIC_STAT_INT, 0x0f);
! 			}
! 			else
! 				sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);
! 		}
! 		/*
! 		 *	Dump the ExCA after IRQ for slot changes
! 		 */
! #ifdef	PCIC_DEBUG
! 		dump_register_table(sp, "set PCIC_STAT_INT");
! #endif
  	}
  #ifdef	PC98
  	if (validslots == 0) {
***************
*** 972,982 ****
  	    return;
  	}	
  #endif
  	if (irq == 0)
  		clrb(sp, PCIC_INT_GEN, 0xF);
! 	else
  		sp->putb(sp, PCIC_INT_GEN, 
! 		    (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq);
  }
  
  /*
--- 1047,1065 ----
  	    return;
  	}	
  #endif
+ #ifdef	PCIC_DEBUG
+ 	printf("pcic: irq=%d mapped.\n", irq);
+ #endif
  	if (irq == 0)
  		clrb(sp, PCIC_INT_GEN, 0xF);
! 	else	{
  		sp->putb(sp, PCIC_INT_GEN, 
! 		    (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq );
! 	}
! #ifdef	PCIC_DEBUG
! 	dump_register_table(sp, "pcic_mapirq()");
! #endif
!  
  }
  
  /*
***************
*** 1051,1056 ****
--- 1134,1140 ----
  
  /*
   *	PCIC timer, it seems that we lose interrupts sometimes
+  *	and we don't get interrupts for the OZ6832 at all ...
   *	so poll just in case...
   */
  static void
***************
*** 1073,1078 ****
--- 1157,1163 ----
  	unsigned char chg;
  	struct pcic_slot *sp = pcic_slots;
  
+ 
  #ifdef	PC98
  	if (sp->controller == PCIC_PC98) {
  	    slot = 0;
***************
*** 1112,1121 ****
  pcic_resume(struct slot *slt)
  {
  	struct pcic_slot *sp = slt->cdata;
  	if (pcic_irq > 0)
! 		sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);
  	if (sp->controller == PCIC_PD672X) {
  		setb(sp, PCIC_MISC1, PCIC_SPKR_EN);
  		setb(sp, PCIC_MISC2, PCIC_LPDM_EN);
  	}
  }
--- 1197,1234 ----
  pcic_resume(struct slot *slt)
  {
  	struct pcic_slot *sp = slt->cdata;
+ 
  	if (pcic_irq > 0)
! 		if(sp->controller == PCIC_OZ6832)	{
! 			printf("pcic: OZ6832 can't steer irqs for slot changes -- irq unused\n");
! 			sp->putb(sp, PCIC_STAT_INT, 0x0f);
! 		}
! 		else
! 			sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF);
! 
  	if (sp->controller == PCIC_PD672X) {
  		setb(sp, PCIC_MISC1, PCIC_SPKR_EN);
  		setb(sp, PCIC_MISC2, PCIC_LPDM_EN);
+ 	}
+ }
+ 
+ 
+ /*
+  * dump all ExCA registers from 800h to 83Fh
+  */
+ void dump_register_table(struct pcic_slot *sp, char *s)
+ {
+ 	unsigned char c;
+ 	unsigned char *p;
+ 	unsigned char regs[16];
+ 	int i, j;
+ 
+ 	printf("\nExCA registers in %s:\n", s);
+ 
+ 	for (i = 0; i < 0x40; i += 16)	{
+ 		for(j=0; j < 16; j++)
+ 			regs[j] = sp->getb(sp, i+j);
+ 		p = regs;
+ 		printf("%02x: %16D\n", i, p, " ");
  	}
  }

--FCuugMFkClbJLl1L--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990215075835.40475>