Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Mar 1998 16:54:51 +0900 (JST)
From:      hosokawa@ntc.keio.ac.jp (HOSOKAWA Tatsumi)
To:        mobile@FreeBSD.ORG
Subject:   Flash ATA/PC-card ATAPI support for -current.
Message-ID:  <199803200754.QAA09200@afs.ntc.mita.keio.ac.jp>

next in thread | raw e-mail | index | archive | help
This is Flash ATA/PC-card ATAPI support for today's -current. Please
test it.

*CAUTION* This works on my laptop (Toshiba Libretto US version), but
it will not work on machines that have secondary IDE interface.

FYI: Sample pccard.conf entries.

# IO Data PCIDE-II (Generic ATAPI interface for CD-ROM, HDD, and MO)
card "IO DATA" "PCIDEII"
	config  0x22 "wdc1" 10

# Hagiwara Sys-com HPC-CFT32 (Compact Flash 32MB)
card "HAGIWARA" "HPC-CFT32"
	config  0x3 "wdc1" 10

--
HOSOKAWA, Tatsumi
Network Technology Center
Keio University
hosokawa@ntc.keio.ac.jp

Index: pccardd/cardd.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pccard/pccardd/cardd.c,v
retrieving revision 1.30
diff -c -r1.30 cardd.c
*** cardd.c	1998/03/09 05:18:50	1.30
--- cardd.c	1998/03/20 07:42:44
***************
*** 189,194 ****
--- 189,195 ----
  	if (sp->cis)
  		freecis(sp->cis);
  	if (sp->config) {
+ logmsg("sp->config->inuse = 0;\n");
  		sp->config->inuse = 0;
  		sp->config->driver->inuse = 0;
  	}
***************
*** 404,409 ****
--- 405,412 ----
  	bzero(&sp->io, sizeof(sp->io));
  	if (cisconf->iospace || (defconf && defconf->iospace)) {
  		struct cis_config *cp;
+ 		int n_iowin = sp->card_config->io_blks;
+ 		int free_ioaddr;
  
  		cp = cisconf;
  		if (!cisconf->iospace)
***************
*** 412,440 ****
   		* If # of I/O lines decoded == 10, then card does its
   		* own decoding.
   		*
   		* If an I/O block exists, then use it.
   		* If no address (but a length) is available, allocate
   		* from the pool.
   		*/
! 		if (cp->io) {
! 			sp->io.addr = cp->io->addr;
! 			sp->io.size = cp->io->size;
! 		} else
  			/*
  			 * No I/O block, assume the address lines
  			 * decode gives the size.
  			 */
  			sp->io.size = 1 << cp->io_addr;
! 
! 		if (sp->io.addr == 0) {
! 			int     i = bit_fns(io_avail, IOPORTS, sp->io.size);
! 
! 			if (i < 0)
  				return (-1);
! 			sp->io.addr = i;
  		}
- 		bit_nclear(io_avail, sp->io.addr,
- 			   sp->io.addr + sp->io.size - 1);
  
  		/* Set up the size to take into account the decode lines. */
  		sp->io.cardaddr = cp->io_addr;
--- 415,465 ----
   		* If # of I/O lines decoded == 10, then card does its
   		* own decoding.
   		*
+  		* If two I/O blocks exist, then use them.
   		* If an I/O block exists, then use it.
   		* If no address (but a length) is available, allocate
   		* from the pool.
   		*/
! 		switch (n_iowin) {
! 		case 0:
  			/*
  			 * No I/O block, assume the address lines
  			 * decode gives the size.
  			 */
  			sp->io.size = 1 << cp->io_addr;
! 			free_ioaddr = bit_fns(io_avail, IOPORTS, sp->io.size);
! 			if (free_ioaddr < 0)
  				return (-1);
! 			sp->io.addr = free_ioaddr;
! 			bit_nclear(io_avail, sp->io.addr, 
! 					sp->io.addr + sp->io.size - 1);
! 			break;
! 		case 1:
! 			sp->io.addr = cp->io->addr;
! 			sp->io.size = cp->io->size;
! 			bit_nclear(io_avail, sp->io.addr, 
! 					sp->io.addr + sp->io.size - 1);
! 			break;
! 		case 2:
! 			sp->io.next = xmalloc(sizeof(struct allocblk));
! 			bzero(sp->io.next, sizeof(struct allocblk));
! 			sp->io.addr = cp->io->addr;
! 			sp->io.size = cp->io->size;
! 			bit_nclear(io_avail, sp->io.addr, 
! 					sp->io.addr + sp->io.size - 1);
! 			if (cp->io->next) {
! 				sp->io.next->addr = cp->io->next->addr;
! 				sp->io.next->size = cp->io->next->size;
! 				bit_nclear(io_avail, 
! 					sp->io.next->addr, 
! 					sp->io.next->addr + sp->io.next->size - 1);
! 			}
! 			break;
! 		default:
! 			/* There's no PC card controller that has more
! 			 * than two I/O windows */
! 			return (-1);
  		}
  
  		/* Set up the size to take into account the decode lines. */
  		sp->io.cardaddr = cp->io_addr;
***************
*** 451,456 ****
--- 476,483 ----
  			sp->io.flags = IODF_WS | IODF_CS16 | IODF_16BIT;
  			break;
  		}
+ 		if (sp->io.next)
+ 			sp->io.next->flags = sp->io.flags;
  #ifdef	DEBUG
  		logmsg("Using I/O addr 0x%x, size %d\n",
  		    sp->io.addr, sp->io.size);
***************
*** 471,476 ****
--- 498,504 ----
  	struct io_desc io;
  	struct dev_desc drv;
  	struct driver *drvp = sp->config->driver;
+ 	struct allocblk	*ab;
  	char    c;
  	off_t   offs;
  	int     rw_flags;
***************
*** 523,549 ****
  			return (0);
  		}
  	}
! 	io.window = 0;
! 	if (sp->io.size) {
! 		io.flags = sp->io.flags;
! 		io.start = sp->io.addr;
! 		io.size = sp->io.size;
! #if 0
! 		io.start = sp->io.addr & ~((1 << sp->io.cardaddr) - 1);
! 		io.size = 1 << sp->io.cardaddr;
! 		if (io.start < 0x100) {
! 			io.start = 0x100;
! 			io.size = 0x300;
! 		}
! #endif
  #ifdef	DEBUG
! 		logmsg("Assigning I/O window %d, start 0x%x, size 0x%x flags 0x%x\n",
! 			io.window, io.start, io.size, io.flags);
  #endif
! 		io.flags |= IODF_ACTIVE;
! 		if (ioctl(sp->fd, PIOCSIO, &io)) {
! 			logerr("ioctl (PIOCSIO)");
! 			return (0);
  		}
  	}
  	strcpy(drv.name, drvp->kernel);
--- 551,570 ----
  			return (0);
  		}
  	}
! 	for (io.window = 0, ab = &sp->io; ab; io.window++, ab = ab->next) {
! 		if (ab->size) {
! 			io.flags = ab->flags;
! 			io.start = ab->addr;
! 			io.size = ab->size;
  #ifdef	DEBUG
! 			logmsg("Assigning I/O window %d, start 0x%x, size 0x%x flags 0x%x\n",
! 				io.window, io.start, io.size, io.flags);
  #endif
! 			io.flags |= IODF_ACTIVE;
! 			if (ioctl(sp->fd, PIOCSIO, &io)) {
! 				logerr("ioctl (PIOCSIO)");
! 				return (0);
! 			}
  		}
  	}
  	strcpy(drv.name, drvp->kernel);
Index: i386/isa/wd.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/wd.c,v
retrieving revision 1.151
diff -c -r1.151 wd.c
*** wd.c	1998/02/16 23:57:41	1.151
--- wd.c	1998/03/20 07:41:39
***************
*** 260,265 ****
--- 260,392 ----
  static int      eide_quirks;
  #endif
  
+ #include "card.h"
+ #if     NCARD > 0
+ #include <sys/select.h>
+ #include <pccard/cardinfo.h>
+ #include <pccard/driver.h>
+ #include <pccard/slot.h>
+ /*
+  *      PC-Card (PCMCIA) specific code.
+  */
+ static int card_intr(struct pccard_devinfo *);	/* Interrupt handler */
+ static void wdunload(struct pccard_devinfo *);	/* Disable driver */
+ static int wdinit(struct pccard_devinfo *);	/* Init. driver */
+ static int wdprobe_pccard(struct isa_device *);	/* Probe PC-card */
+ 
+ static struct pccard_device wdinfo =
+ {
+ 	"wdc",
+ 	wdinit,
+ 	wdunload,
+ 	card_intr,
+ 	0,			/* Attributes - presently unused */
+ 	&bio_imask		/* Interrupt mask for device */
+ };
+ 
+ DATA_SET(pccarddrv_set, wdinfo);
+ 
+ static int static_init = 1;
+ static int lunit_in_use = 0;
+ static int ctrlr_in_use = 0;
+ 
+ 
+ /*
+  * Initialize the device - called from Slot manager.
+  * if first is set, then initially check for
+  * the device's existence before initialising it.
+  * Once initialised, the device table may be set up.
+  */
+ static int
+ wdinit(struct pccard_devinfo *dp)
+ {
+ /*
+  *	dynamic configuration mode
+  */
+ 	static_init = 0;
+ /*
+  *	validate unit number.
+  */
+ 	if (dp->isahd.id_unit >= NWDC)
+ 		return(ENODEV);
+ /*
+  *	Probe the device. If a value is returned, the
+  *	device was found at the location.
+  */
+ 
+ 	if (wdprobe_pccard(&dp->isahd)==0) {
+ 		if (bootverbose)
+ 			printf("Probe Failed\n");
+ 		return(ENXIO);
+ 	}
+ 	if (wdattach(&dp->isahd)==0) {
+ 		if (bootverbose)
+ 			printf("Attach Failed\n");
+ 		return(ENXIO);
+ 	}
+ 
+ 	ctrlr_in_use |= (1 << dp->isahd.id_unit);
+ /*
+  *	XXX TODO:
+  *	If it was already inited before, the device structure
+  *	should be already initialised. Here we should
+  *	reset (and possibly restart) the hardware, but
+  *	I am not sure of the best way to do this...
+  */
+ 	return(0);
+ }
+ 
+ /*
+  *	wdunload - unload the driver and clear the table.
+  *	XXX TODO:
+  *	This is called usually when the card is ejected, but
+  *	can be caused by the modunload of a controller driver.
+  *	The idea is reset the driver's view of the device
+  *	and ensure that any driver entry points such as
+  *	read and write do not hang.
+  */
+ static void
+ wdunload(struct pccard_devinfo *dp)
+ {
+ 	int ctrlr = dp->isahd.id_unit;
+ 	int lunit;
+ 
+ 	for (lunit = 0; lunit < NWD; lunit++) {
+ 		if ((lunit_in_use & (1<<lunit)) && wddrives[lunit] &&
+ 			wddrives[lunit]->dk_ctrlr == ctrlr &&
+ 			wddrives[lunit]->dk_port  == dp->isahd.id_iobase ) {
+ 			lunit_in_use &= ~(1<<lunit);
+ 			break;
+ 		}
+ 	}
+ 	ctrlr_in_use &= ~(1 << ctrlr);
+ 	if (bootverbose) {
+ 		printf("wdc%d: unloading -- ", ctrlr);
+ 		if (wdtab[ctrlr].b_active != 0)
+ 			printf("damage!\n");
+ 		else
+ 			printf("done\n");
+ 	}
+ }
+ 
+ /*
+  *	card_intr - Shared interrupt called from
+  *	front end of PC-Card handler.
+  */
+ static int
+ card_intr(struct pccard_devinfo *dp)
+ {
+ 	wdintr(dp->isahd.id_unit);
+ 	return(1);
+ }
+ 
+ static int
+ wdprobe_pccard(struct isa_device *isa_dev)
+ {
+ 	return wdprobe(isa_dev);
+ }
+ #endif  /* NCARD > 0 */
+ 
  
  /*
   *  Here we use the pci-subsystem to find out, whether there is
***************
*** 288,293 ****
--- 415,429 ----
  	if (unit >= NWDC)
  		return (0);
  
+ #if	NCARD > 0
+ /*
+  *	If PC-Card probe required, then register driver with
+  *	slot manager.
+  */
+ 	if (!static_init && (ctrlr_in_use & (1 << unit)))
+ 		return (0);
+ #endif  /* NCARD > 0 */
+  
  	du = malloc(sizeof *du, M_TEMP, M_NOWAIT);
  	if (du == NULL)
  		return (0);
***************
*** 387,393 ****
  			goto nodevice;
  	}
  
- 
  	free(du, M_TEMP);
  	return (IO_WDCSIZE);
  
--- 523,528 ----
***************
*** 409,414 ****
--- 544,554 ----
  	struct isa_device *wdup;
  	struct disk *du;
  	struct wdparams *wp;
+ #if	NCARD > 0
+ 	static int once_registered = 0;
+ 	static int old_dkunit[NWD];
+ 	int valid_units = 0;
+ #endif	/* NCARD > 0 */
  
  	if (dvp->id_unit >= NWDC)
  		return (0);
***************
*** 430,445 ****
--- 570,604 ----
  		if (wdup->id_iobase != dvp->id_iobase)
  			continue;
  		lunit = wdup->id_unit;
+ 
+ #if	NCARD > 0
+ 		if (lunit_in_use & (1 << lunit)) {
+ 			if (static_init)
+ 				panic("drive attached twice");
+ 			else
+ 				continue;
+ 		}
+ #endif	/* NCARD > 0 */
+ 
  		if (lunit >= NWD)
  			continue;
  
  		unit = wdup->id_physid;
  
+ #if	NCARD > 0
+ 		du = wddrives[lunit];
+ 		if (du == NULL)
+ 			du = malloc(sizeof *du, M_TEMP, M_NOWAIT);
+ 		if (du == NULL)
+ 			continue;
+ #else	/* NCARD > 0 */
  		du = malloc(sizeof *du, M_TEMP, M_NOWAIT);
  		if (du == NULL)
  			continue;
  		if (wddrives[lunit] != NULL)
  			panic("drive attached twice");
+ #endif	/* NCARD > 0 */
+ 
  		wddrives[lunit] = du;
  		bufq_init(&drive_queue[lunit]);
  		bzero(du, sizeof *du);
***************
*** 512,517 ****
--- 671,687 ----
  			 * XXX timeout should be per controller.
  			 */
  			wdtimeout(du);
+ #if	NCARD > 0
+ 			lunit_in_use |= (1 << lunit);
+ 			valid_units++;
+ 			/* do not register twice */
+ 			if (once_registered & (1 << lunit)) {
+                         	/* reuse previous dk_dkunit */
+                         	du->dk_dkunit = old_dkunit[lunit];
+ 				goto reuse_it;
+ 			}
+ 			once_registered |= (1 << lunit);
+ #endif  /* NCARD > 0 */
  
  #ifdef DEVFS
  			mynor = dkmakeminor(lunit, WHOLE_DISK_SLICE, RAW_PART);
***************
*** 534,543 ****
--- 704,724 ----
  				 * according to iostat.
  				 */
  				dk_wpms[dk_ndrive] = 4 * 1024 * 1024 / 2;
+ #if	NCARD > 0
+ 				old_dkunit[lunit] = du->dk_dkunit = dk_ndrive++;
+ #else	/* NCARD > 0 */
  				du->dk_dkunit = dk_ndrive++;
+ #endif	/* NCARD > 0 */
  			} else {
+ #if	NCARD > 0
+ 				old_dkunit[lunit] = du->dk_dkunit = -1;
+ #else	/* NCARD > 0 */
  				du->dk_dkunit = -1;
+ #endif	/* NCARD > 0 */
  			}
+ #if     NCARD > 0
+ reuse_it:
+ #endif /* NCARD > 0 */
  		} else {
  			free(du, M_TEMP);
  			wddrives[lunit] = NULL;
***************
*** 548,567 ****
  	 * Probe all free IDE units, searching for ATAPI drives.
  	 */
  	for (unit=0; unit<2; ++unit) {
  		for (lunit=0; lunit<NWD; ++lunit)
  			if (wddrives[lunit] &&
  			    wddrives[lunit]->dk_ctrlr == dvp->id_unit &&
  			    wddrives[lunit]->dk_unit == unit)
  				goto next;
  #ifdef CMD640
  		if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase))
  			atapictrlr = dvp->id_unit;
! #else
  		atapi_attach (dvp->id_unit, unit, dvp->id_iobase);
! #endif
  next: ;
  	}
! #endif
  	/*
  	 * Discard any interrupts generated by wdgetctlr().  wdflushirq()
  	 * doesn't work now because the ambient ipl is too high.
--- 729,768 ----
  	 * Probe all free IDE units, searching for ATAPI drives.
  	 */
  	for (unit=0; unit<2; ++unit) {
+ #if	NCARD > 0
+ 		for (lunit=0; lunit<NWD; ++lunit)
+ 			if ((lunit_in_use & (1<<lunit)) && wddrives[lunit] &&
+ 				wddrives[lunit]->dk_ctrlr == dvp->id_unit &&
+ 				wddrives[lunit]->dk_unit == unit)
+ 				goto next;
+ #else	/* NCARD > 0 */
  		for (lunit=0; lunit<NWD; ++lunit)
  			if (wddrives[lunit] &&
  			    wddrives[lunit]->dk_ctrlr == dvp->id_unit &&
  			    wddrives[lunit]->dk_unit == unit)
  				goto next;
+ #endif	/* NCARD > 0 */
  #ifdef CMD640
+ #if	NCARD > 0
+ 		if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase)) {
+ 			atapictrlr = dvp->id_unit;
+ 			valid_units++;
+ 		}
+ #else	/* NCARD > 0 */
  		if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase))
  			atapictrlr = dvp->id_unit;
! #endif	/* NCARD > 0 */
! #else	/* CMD640 */
! #if	NCARD > 0
! 		if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase))
! 			valid_units++;
! #else	/* NCARD > 0 */
  		atapi_attach (dvp->id_unit, unit, dvp->id_iobase);
! #endif	/* NCARD > 0 */
! #endif	/* CMD640 */
  next: ;
  	}
! #endif	/* ATAPI */
  	/*
  	 * Discard any interrupts generated by wdgetctlr().  wdflushirq()
  	 * doesn't work now because the ambient ipl is too high.
***************
*** 572,580 ****
  	} else {
  		wdtab[dvp->id_unit].b_active = 2;
  	}
! #else
  	wdtab[dvp->id_unit].b_active = 2;
! #endif
  
  	return (1);
  }
--- 773,786 ----
  	} else {
  		wdtab[dvp->id_unit].b_active = 2;
  	}
! #else	/* CMD640 */
  	wdtab[dvp->id_unit].b_active = 2;
! #endif	/* CMD640 */
! 
! #if	NCARD > 0
! 	if (!static_init && valid_units == 0)
! 		return (0); /* no valid unit found */
! #endif	/* NCARD > 0 */
  
  	return (1);
  }
***************
*** 1287,1292 ****
--- 1493,1503 ----
  	lunit = dkunit(dev);
  	if (lunit >= NWD || dktype(dev) != 0)
  		return (ENXIO);
+ #if	NCARD > 0
+ 	if ((lunit_in_use & (1<<lunit)) == 0)
+ 		return (ENXIO);
+ #endif	/* NCARD > 0 */
+ 
  	du = wddrives[lunit];
  	if (du == NULL)
  		return (ENXIO);
***************
*** 2025,2030 ****
--- 2236,2244 ----
  	lunit = dkunit(dev);	/* eventually support floppies? */
  	part = dkpart(dev);
  	if (lunit >= NWD || (du = wddrives[lunit]) == NULL
+ #if NCARD > 0
+ 	    || (lunit_in_use & (1 << lunit)) == 0
+ #endif /* NCARD > 0 */
  	    || du->dk_state < OPEN
  	    || (lp = dsgetlabel(dev, du->dk_slices)) == NULL)
  		return (ENXIO);

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?199803200754.QAA09200>