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>
