From owner-freebsd-mobile Thu Mar 19 23:55:06 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id XAA15909 for freebsd-mobile-outgoing; Thu, 19 Mar 1998 23:55:06 -0800 (PST) (envelope-from owner-freebsd-mobile@FreeBSD.ORG) Received: from afs.ntc.mita.keio.ac.jp (afs.ntc.mita.keio.ac.jp [131.113.212.3]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id XAA15902 for ; Thu, 19 Mar 1998 23:55:01 -0800 (PST) (envelope-from hosokawa@ntc.keio.ac.jp) Received: (from hosokawa@localhost) by afs.ntc.mita.keio.ac.jp (8.8.8+2.7Wbeta7/3.6Wbeta6-ntc_mailserver1.03) id QAA09200; Fri, 20 Mar 1998 16:54:51 +0900 (JST) Date: Fri, 20 Mar 1998 16:54:51 +0900 (JST) Message-Id: <199803200754.QAA09200@afs.ntc.mita.keio.ac.jp> To: mobile@FreeBSD.ORG Subject: Flash ATA/PC-card ATAPI support for -current. From: hosokawa@ntc.keio.ac.jp (HOSOKAWA Tatsumi) X-Mailer: mnews [version 1.20] 1996-12/08(Sun) Sender: owner-freebsd-mobile@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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 + #include + #include + #include + /* + * 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<dk_ctrlr == ctrlr && + wddrives[lunit]->dk_port == dp->isahd.id_iobase ) { + lunit_in_use &= ~(1<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; lunitdk_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; lunitdk_ctrlr == dvp->id_unit && + wddrives[lunit]->dk_unit == unit) + goto next; + #else /* NCARD > 0 */ for (lunit=0; lunitdk_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< 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