Subject: Compact Flash memory mapped addressing patch.
To: None <tech-kern@netbsd.org>
From: UCHIYAMA Yasushi <uch@nop.or.jp>
List: tech-kern
Date: 03/07/2001 23:55:22
 Hitachi HD64461 pcmcia controller channel 1 don't support I/O card
but can attach CF using memory mapped mode. this patch enables memory
mapped CF mode if its entry exists in CIS and PCMCIA controller don't
support I/O space.
 Do you think about this modification?
---
UCHIYAMA Yasushi
uch@nop.or.jp

Index: wdc_pcmcia.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pcmcia/wdc_pcmcia.c,v
retrieving revision 1.40
diff -u -r1.40 wdc_pcmcia.c
--- wdc_pcmcia.c	2001/02/21 21:39:56	1.40
+++ wdc_pcmcia.c	2001/03/06 15:58:48
@@ -61,12 +61,17 @@
 	struct channel_softc wdc_channel;
 	struct pcmcia_io_handle sc_pioh;
 	struct pcmcia_io_handle sc_auxpioh;
+	struct pcmcia_mem_handle sc_pmembaseh;
+	struct pcmcia_mem_handle sc_pmemh;
+	struct pcmcia_mem_handle sc_auxpmemh;
+	int sc_memwindow;
 	int sc_iowindow;
 	int sc_auxiowindow;
 	void *sc_ih;
 	struct pcmcia_function *sc_pf;
 	int sc_flags;
 #define	WDC_PCMCIA_ATTACH	0x0001
+#define WDC_PCMCIA_MEMMODE	0x0002
 };
 
 static int wdc_pcmcia_match	__P((struct device *, struct cfdata *, void *));
@@ -213,6 +218,7 @@
 	struct pcmcia_attach_args *pa = aux;
 	struct pcmcia_config_entry *cfe;
 	const struct wdc_pcmcia_product *wpp;
+	bus_addr_t offset;
 	int quirks;
 
 	sc->sc_pf = pa->pf;
@@ -242,6 +248,22 @@
 		pcmcia_io_free(pa->pf, &sc->sc_pioh);
 	}
 
+	/* 
+	 * Compact Falsh memory mapped mode
+	 * CF+ and CompactFlash Spec. Rev 1.4, 6.1.3 Memory Mapped Addressing.
+	 */
+	if (cfe == NULL) {
+		SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
+			if (cfe->iftype != PCMCIA_IFTYPE_MEMORY)
+				continue;
+			if (pcmcia_mem_alloc(pa->pf, cfe->memspace[0].length,
+			    &sc->sc_pmembaseh) == 0) {
+				sc->sc_flags |= WDC_PCMCIA_MEMMODE;
+				break;
+			}
+		}
+	}
+
 	if (cfe == NULL) {
 		printf(": can't handle card info\n");
 		goto no_config_entry;
@@ -260,18 +282,45 @@
 	else
 		quirks = 0;
 
-	if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0,
-	    sc->sc_pioh.size, &sc->sc_pioh, &sc->sc_iowindow)) {
-		printf(": can't map first I/O space\n");
-		goto iomap_failed;
-	} 
+	if (sc->sc_flags & WDC_PCMCIA_MEMMODE) {
+		if (pcmcia_mem_map(pa->pf, PCMCIA_MEM_COMMON, 0,
+		    sc->sc_pmembaseh.size, &sc->sc_pmembaseh, &offset,
+		    &sc->sc_memwindow)) {
+			printf(": can't map memory space\n");
+			goto map_failed;
+		}
 
-	if (cfe->num_iospace <= 1)
+		sc->sc_pmemh.memt = sc->sc_pmembaseh.memt;
+		if (offset == 0) {
+			sc->sc_pmemh.memh = sc->sc_pmembaseh.memh;
+		} else {
+			if (bus_space_subregion(sc->sc_pmemh.memt,
+				sc->sc_pmembaseh.memh, offset,
+				WDC_PCMCIA_REG_NPORTS, &sc->sc_pmemh.memh))
+				goto mapaux_failed;
+		}
+
+		sc->sc_auxpmemh.memt = sc->sc_pmemh.memt;
+		if (bus_space_subregion(sc->sc_pmemh.memt,
+		    sc->sc_pmemh.memh, WDC_PCMCIA_AUXREG_OFFSET,
+		    WDC_PCMCIA_AUXREG_NPORTS, &sc->sc_auxpmemh.memh))
+			goto mapaux_failed;
+		
+		printf(" memory mapped mode");
+	} else {
+		if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0,
+		    sc->sc_pioh.size, &sc->sc_pioh, &sc->sc_iowindow)) {
+			printf(": can't map first I/O space\n");
+			goto map_failed;
+		} 
+	}
+
+	if (cfe->num_iospace <= 1 || sc->sc_flags & WDC_PCMCIA_MEMMODE)
 		sc->sc_auxiowindow = -1;
 	else if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0,
 	    sc->sc_auxpioh.size, &sc->sc_auxpioh, &sc->sc_auxiowindow)) {
 		printf(": can't map second I/O space\n");
-		goto iomapaux_failed;
+		goto mapaux_failed;
 	}
 
 	if ((wpp != NULL) && (wpp->wpp_name != NULL))
@@ -279,13 +328,21 @@
 	
 	printf("\n");
 
-	sc->wdc_channel.cmd_iot = sc->sc_pioh.iot;
-	sc->wdc_channel.cmd_ioh = sc->sc_pioh.ioh;
-	sc->wdc_channel.ctl_iot = sc->sc_auxpioh.iot;
-	sc->wdc_channel.ctl_ioh = sc->sc_auxpioh.ioh;
+	sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16;
+	if (sc->sc_flags & WDC_PCMCIA_MEMMODE) {
+		sc->wdc_channel.cmd_iot = sc->sc_pmemh.memt;
+		sc->wdc_channel.cmd_ioh = sc->sc_pmemh.memh;
+		sc->wdc_channel.ctl_iot = sc->sc_auxpmemh.memt;
+		sc->wdc_channel.ctl_ioh = sc->sc_auxpmemh.memh;
+	} else {
+		sc->wdc_channel.cmd_iot = sc->sc_pioh.iot;
+		sc->wdc_channel.cmd_ioh = sc->sc_pioh.ioh;
+		sc->wdc_channel.ctl_iot = sc->sc_auxpioh.iot;
+		sc->wdc_channel.ctl_ioh = sc->sc_auxpioh.ioh;
+		sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA32;
+	}
 	sc->wdc_channel.data32iot = sc->wdc_channel.cmd_iot;
 	sc->wdc_channel.data32ioh = sc->wdc_channel.cmd_ioh;
-	sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32;
 	sc->sc_wdcdev.cap |= WDC_CAPABILITY_SINGLE_DRIVE;
 	sc->sc_wdcdev.PIO_cap = 0;
 	sc->wdc_chanptr = &sc->wdc_channel;
@@ -314,23 +371,29 @@
 
  ch_queue_alloc_failed:
 	/* Unmap our aux i/o window. */
-	if (sc->sc_auxiowindow != -1)
+	if (!(sc->sc_flags & WDC_PCMCIA_MEMMODE) && (sc->sc_auxiowindow != -1))
 		pcmcia_io_unmap(sc->sc_pf, sc->sc_auxiowindow);
 
- iomapaux_failed:
+ mapaux_failed:
 	/* Unmap our i/o window. */
-	pcmcia_io_unmap(sc->sc_pf, sc->sc_iowindow);
+	if (sc->sc_flags & WDC_PCMCIA_MEMMODE)
+		pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwindow);
+	else
+		pcmcia_io_unmap(sc->sc_pf, sc->sc_iowindow);
 
- iomap_failed:
+ map_failed:
 	/* Disable the function */
 	pcmcia_function_disable(sc->sc_pf);
 
  enable_failed:
 	/* Unmap our i/o space. */
-	pcmcia_io_free(sc->sc_pf, &sc->sc_pioh);
-	if (cfe->num_iospace == 2)
-		pcmcia_io_free(sc->sc_pf, &sc->sc_auxpioh);
-
+	if (sc->sc_flags & WDC_PCMCIA_MEMMODE) {
+		pcmcia_mem_free(sc->sc_pf, &sc->sc_pmembaseh);
+	} else  {
+		pcmcia_io_free(sc->sc_pf, &sc->sc_pioh);
+		if (cfe->num_iospace == 2)
+		    pcmcia_io_free(sc->sc_pf, &sc->sc_auxpioh);
+	}
  no_config_entry:
 	sc->sc_iowindow = -1;
 }
@@ -354,11 +417,16 @@
 		free(sc->wdc_channel.ch_queue, M_DEVBUF);
 
 	/* Unmap our i/o window and i/o space. */
-	pcmcia_io_unmap(sc->sc_pf, sc->sc_iowindow);
-	pcmcia_io_free(sc->sc_pf, &sc->sc_pioh);
-	if (sc->sc_auxiowindow != -1) {
-		pcmcia_io_unmap(sc->sc_pf, sc->sc_auxiowindow);
-		pcmcia_io_free(sc->sc_pf, &sc->sc_auxpioh);
+	if (sc->sc_flags & WDC_PCMCIA_MEMMODE) {
+		pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwindow);
+		pcmcia_mem_free(sc->sc_pf, &sc->sc_pmembaseh);
+	} else {
+		pcmcia_io_unmap(sc->sc_pf, sc->sc_iowindow);
+		pcmcia_io_free(sc->sc_pf, &sc->sc_pioh);
+		if (sc->sc_auxiowindow != -1) {
+			pcmcia_io_unmap(sc->sc_pf, sc->sc_auxiowindow);
+			pcmcia_io_free(sc->sc_pf, &sc->sc_auxpioh);
+		}
 	}
 
 	return (0);