1999-08-06 15:59:07 +00:00
|
|
|
/*
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
|
|
|
* <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
|
|
|
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
|
|
|
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
*
|
1999-08-28 02:16:32 +00:00
|
|
|
* $FreeBSD$
|
1999-08-06 15:59:07 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/kernel.h>
|
2000-05-05 09:59:14 +00:00
|
|
|
#include <sys/bio.h>
|
1999-08-06 15:59:07 +00:00
|
|
|
#include <sys/malloc.h>
|
1999-09-12 09:16:00 +00:00
|
|
|
#include <sys/conf.h>
|
1999-08-29 13:29:29 +00:00
|
|
|
#include <sys/disk.h>
|
1999-08-15 14:30:09 +00:00
|
|
|
#include <sys/devicestat.h>
|
1999-08-06 15:59:07 +00:00
|
|
|
#include <sys/module.h>
|
|
|
|
#include <machine/resource.h>
|
|
|
|
|
|
|
|
#include <vm/vm.h>
|
|
|
|
#include <vm/pmap.h>
|
|
|
|
#include <vm/vm_param.h>
|
|
|
|
|
|
|
|
#include <sys/bus.h>
|
|
|
|
|
1999-08-29 13:29:29 +00:00
|
|
|
#define LEAVE()
|
|
|
|
#define ENTER()
|
1999-08-06 15:59:07 +00:00
|
|
|
|
1999-08-07 13:11:12 +00:00
|
|
|
#include <contrib/dev/fla/msysosak.h>
|
1999-08-06 15:59:07 +00:00
|
|
|
|
2000-12-08 20:09:00 +00:00
|
|
|
static MALLOC_DEFINE(M_FLA, "fla driver", "fla driver storage");
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
static int fla_debug = 0;
|
|
|
|
SYSCTL_INT(_debug, OID_AUTO, fladebug, CTLFLAG_RW, &fla_debug, 0, "");
|
|
|
|
|
|
|
|
#define CDEV_MAJOR 102
|
|
|
|
|
|
|
|
static d_strategy_t flastrategy;
|
|
|
|
static d_open_t flaopen;
|
|
|
|
static d_close_t flaclose;
|
|
|
|
static d_ioctl_t flaioctl;
|
|
|
|
|
|
|
|
static struct cdevsw fla_cdevsw = {
|
|
|
|
/* open */ flaopen,
|
|
|
|
/* close */ flaclose,
|
|
|
|
/* read */ physread,
|
|
|
|
/* write */ physwrite,
|
|
|
|
/* ioctl */ flaioctl,
|
|
|
|
/* poll */ nopoll,
|
|
|
|
/* mmap */ nommap,
|
|
|
|
/* strategy */ flastrategy,
|
|
|
|
/* name */ "fla",
|
|
|
|
/* maj */ CDEV_MAJOR,
|
|
|
|
/* dump */ nodump,
|
1999-08-29 13:29:29 +00:00
|
|
|
/* psize */ nopsize,
|
1999-08-06 15:59:07 +00:00
|
|
|
/* flags */ D_DISK | D_CANFREE,
|
|
|
|
};
|
1999-09-12 20:40:29 +00:00
|
|
|
static struct cdevsw fladisk_cdevsw;
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
void *
|
|
|
|
doc2k_malloc(int bytes)
|
|
|
|
{
|
|
|
|
return malloc(bytes, M_FLA, M_WAITOK);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
doc2k_free(void *ptr)
|
|
|
|
{
|
|
|
|
free(ptr, M_FLA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
doc2k_delay(unsigned msec)
|
|
|
|
{
|
|
|
|
DELAY(1000 * msec);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
doc2k_memcpy(void *dst, const void *src, unsigned len)
|
|
|
|
{
|
|
|
|
bcopy(src, dst, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
doc2k_memcmp(const void *dst, const void *src, unsigned len)
|
|
|
|
{
|
|
|
|
return (bcmp(src, dst, len));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
doc2k_memset(void *dst, int c, unsigned len)
|
|
|
|
{
|
|
|
|
u_char *p = dst;
|
|
|
|
while (len--)
|
|
|
|
*p++ = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct fla_s {
|
1999-08-29 13:29:29 +00:00
|
|
|
int busy;
|
|
|
|
int unit;
|
1999-08-06 15:59:07 +00:00
|
|
|
unsigned nsect;
|
|
|
|
struct doc2k_stat ds;
|
2000-04-15 05:54:02 +00:00
|
|
|
struct bio_queue_head bio_queue;
|
1999-08-15 14:30:09 +00:00
|
|
|
struct devstat stats;
|
1999-08-29 13:29:29 +00:00
|
|
|
struct disk disk;
|
|
|
|
dev_t dev;
|
2000-04-23 09:10:09 +00:00
|
|
|
} softc[8];
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
flaopen(dev_t dev, int flag, int fmt, struct thread *td)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
|
|
|
struct fla_s *sc;
|
|
|
|
int error;
|
1999-08-29 13:29:29 +00:00
|
|
|
struct disklabel *dl;
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
if (fla_debug)
|
1999-08-29 13:29:29 +00:00
|
|
|
printf("flaopen(%s %x %x %p)\n",
|
2001-09-12 08:38:13 +00:00
|
|
|
devtoname(dev), flag, fmt, td);
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
sc = dev->si_drv1;
|
|
|
|
|
|
|
|
error = doc2k_open(sc->unit);
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
printf("doc2k_open(%d) -> err %d\n", sc->unit, error);
|
|
|
|
return (EIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
dl = &sc->disk.d_label;
|
|
|
|
bzero(dl, sizeof(*dl));
|
|
|
|
error = doc2k_size(sc->unit, &dl->d_secperunit,
|
|
|
|
&dl->d_ncylinders, &dl->d_ntracks, &dl->d_nsectors);
|
|
|
|
dl->d_secsize = DEV_BSIZE;
|
|
|
|
dl->d_secpercyl = dl->d_ntracks * dl->d_nsectors; /* XXX */
|
|
|
|
|
1999-08-14 11:40:51 +00:00
|
|
|
return (0);
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
flaclose(dev_t dev, int flags, int fmt, struct thread *td)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
1999-08-29 13:29:29 +00:00
|
|
|
int error;
|
1999-08-06 15:59:07 +00:00
|
|
|
struct fla_s *sc;
|
|
|
|
|
|
|
|
if (fla_debug)
|
1999-08-29 13:29:29 +00:00
|
|
|
printf("flaclose(%s %x %x %p)\n",
|
2001-09-12 08:38:13 +00:00
|
|
|
devtoname(dev), flags, fmt, td);
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
sc = dev->si_drv1;
|
|
|
|
|
|
|
|
error = doc2k_close(sc->unit);
|
|
|
|
if (error) {
|
|
|
|
printf("doc2k_close(%d) -> err %d\n", sc->unit, error);
|
|
|
|
return (EIO);
|
|
|
|
}
|
1999-08-06 15:59:07 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-09-12 08:38:13 +00:00
|
|
|
flaioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
if (fla_debug)
|
1999-08-29 13:29:29 +00:00
|
|
|
printf("flaioctl(%s %lx %p %x %p)\n",
|
2001-09-12 08:38:13 +00:00
|
|
|
devtoname(dev), cmd, addr, flags, td);
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
return (ENOIOCTL);
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-04-15 05:54:02 +00:00
|
|
|
flastrategy(struct bio *bp)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
|
|
|
int unit, error;
|
1999-08-15 14:30:09 +00:00
|
|
|
int s;
|
1999-08-06 15:59:07 +00:00
|
|
|
struct fla_s *sc;
|
|
|
|
enum doc2k_work what;
|
|
|
|
|
1999-08-14 11:40:51 +00:00
|
|
|
if (fla_debug > 1)
|
2002-03-19 20:46:30 +00:00
|
|
|
printf("flastrategy(%p) %s %x, %lld, %ld, %p)\n",
|
|
|
|
bp, devtoname(bp->bio_dev), bp->bio_flags,
|
|
|
|
(long long)bp->bio_blkno,
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_bcount / DEV_BSIZE, bp->bio_data);
|
1999-08-06 15:59:07 +00:00
|
|
|
|
2000-04-15 05:54:02 +00:00
|
|
|
sc = bp->bio_dev->si_drv1;
|
1999-08-06 15:59:07 +00:00
|
|
|
|
1999-08-15 14:30:09 +00:00
|
|
|
s = splbio();
|
1999-08-06 15:59:07 +00:00
|
|
|
|
2000-04-15 05:54:02 +00:00
|
|
|
bioqdisksort(&sc->bio_queue, bp);
|
1999-08-06 15:59:07 +00:00
|
|
|
|
1999-08-15 14:30:09 +00:00
|
|
|
if (sc->busy) {
|
|
|
|
splx(s);
|
1999-08-06 15:59:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-08-15 14:30:09 +00:00
|
|
|
sc->busy++;
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
while (1) {
|
2000-04-15 05:54:02 +00:00
|
|
|
bp = bioq_first(&sc->bio_queue);
|
1999-08-06 15:59:07 +00:00
|
|
|
if (bp)
|
2000-04-15 05:54:02 +00:00
|
|
|
bioq_remove(&sc->bio_queue, bp);
|
1999-08-15 14:30:09 +00:00
|
|
|
splx(s);
|
1999-08-06 15:59:07 +00:00
|
|
|
if (!bp)
|
|
|
|
break;
|
|
|
|
|
1999-08-15 14:30:09 +00:00
|
|
|
devstat_start_transaction(&sc->stats);
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_resid = bp->bio_bcount;
|
|
|
|
unit = dkunit(bp->bio_dev);
|
1999-08-06 15:59:07 +00:00
|
|
|
|
2000-04-15 05:54:02 +00:00
|
|
|
if (bp->bio_cmd == BIO_DELETE)
|
1999-09-18 21:30:27 +00:00
|
|
|
what = DOC2K_ERASE;
|
2000-04-15 05:54:02 +00:00
|
|
|
else if (bp->bio_cmd == BIO_READ)
|
1999-09-18 21:30:27 +00:00
|
|
|
what = DOC2K_READ;
|
1999-08-06 15:59:07 +00:00
|
|
|
else
|
1999-09-18 21:30:27 +00:00
|
|
|
what = DOC2K_WRITE;
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
LEAVE();
|
|
|
|
|
2000-04-15 05:54:02 +00:00
|
|
|
error = doc2k_rwe( unit, what, bp->bio_pblkno,
|
|
|
|
bp->bio_bcount / DEV_BSIZE, bp->bio_data);
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
ENTER();
|
1999-08-06 15:59:07 +00:00
|
|
|
|
1999-08-14 11:40:51 +00:00
|
|
|
if (fla_debug > 1 || error) {
|
2002-03-19 20:46:30 +00:00
|
|
|
printf("fla%d: %d = rwe(%p, %d, %d, %lld, %ld, %p)\n",
|
|
|
|
unit, error, bp, unit, what,
|
|
|
|
(long long)bp->bio_pblkno,
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_bcount / DEV_BSIZE, bp->bio_data);
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
|
|
|
if (error) {
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_error = EIO;
|
|
|
|
bp->bio_flags |= BIO_ERROR;
|
1999-08-06 15:59:07 +00:00
|
|
|
} else {
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_resid = 0;
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
2001-05-06 20:00:03 +00:00
|
|
|
biofinish(bp, &sc->stats, 0);
|
1999-08-06 15:59:07 +00:00
|
|
|
|
1999-08-15 14:30:09 +00:00
|
|
|
s = splbio();
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
1999-08-15 14:30:09 +00:00
|
|
|
sc->busy = 0;
|
1999-08-06 15:59:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1999-08-29 13:29:29 +00:00
|
|
|
flaprobe (device_t dev)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
|
|
|
int unit;
|
|
|
|
struct fla_s *sc;
|
|
|
|
int i;
|
|
|
|
|
1999-08-29 13:29:29 +00:00
|
|
|
unit = device_get_unit(dev);
|
2000-04-23 09:10:09 +00:00
|
|
|
if (unit >= 8)
|
|
|
|
return (ENXIO);
|
1999-08-06 15:59:07 +00:00
|
|
|
sc = &softc[unit];
|
|
|
|
|
|
|
|
/* This is slightly ugly */
|
|
|
|
i = doc2k_probe(unit, KERNBASE + 0xc0000, KERNBASE + 0xe0000);
|
|
|
|
if (i)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
i = doc2k_info(unit, &sc->ds);
|
|
|
|
if (i)
|
|
|
|
return (ENXIO);
|
|
|
|
|
* Add struct resource_list* argument to resource_list_alloc and
resource_list_release. This removes the dependancy on the
layout of ivars.
* Move set_resource, get_resource and delete_resource from
isa_if.m to bus_if.m.
* Simplify driver code by providing wrappers to those methods:
bus_set_resource(dev, type, rid, start, count);
bus_get_resource(dev, type, rid, startp, countp);
bus_get_resource_start(dev, type, rid);
bus_get_resource_count(dev, type, rid);
bus_delete_resource(dev, type, rid);
* Delete isa_get_rsrc and use bus_get_resource_start instead.
* Fix a stupid typo in isa_alloc_resource reported by Takahashi
Yoshihiro <nyan@FreeBSD.org>.
* Print a diagnostic message if we can't assign resources to a PnP
device.
* Change device_print_prettyname() so that it doesn't print
"(no driver assigned)-1" for anonymous devices.
1999-10-12 21:35:51 +00:00
|
|
|
bus_set_resource(dev, SYS_RES_MEMORY, 0,
|
1999-08-29 13:29:29 +00:00
|
|
|
sc->ds.window - KERNBASE, 8192);
|
|
|
|
|
1999-08-06 15:59:07 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1999-08-29 13:29:29 +00:00
|
|
|
flaattach (device_t dev)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
1999-08-29 13:29:29 +00:00
|
|
|
int unit;
|
1999-08-06 15:59:07 +00:00
|
|
|
int i, j, k, l, m, error;
|
|
|
|
struct fla_s *sc;
|
|
|
|
|
1999-08-29 13:29:29 +00:00
|
|
|
unit = device_get_unit(dev);
|
1999-08-06 15:59:07 +00:00
|
|
|
sc = &softc[unit];
|
|
|
|
|
|
|
|
error = doc2k_open(unit);
|
|
|
|
if (error) {
|
|
|
|
printf("doc2k_open(%d) -> err %d\n", unit, error);
|
|
|
|
return (EIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
error = doc2k_size(unit, &sc->nsect, &i, &j, &k );
|
|
|
|
if (error) {
|
|
|
|
printf("doc2k_size(%d) -> err %d\n", unit, error);
|
|
|
|
return (EIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("fla%d: <%s %s>\n", unit, sc->ds.product, sc->ds.model);
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
error = doc2k_close(unit);
|
|
|
|
if (error) {
|
|
|
|
printf("doc2k_close(%d) -> err %d\n", unit, error);
|
|
|
|
return (EIO);
|
|
|
|
}
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
m = 1024L * 1024L / DEV_BSIZE;
|
|
|
|
l = (sc->nsect * 10 + m/2) / m;
|
|
|
|
printf("fla%d: %d.%01dMB (%u sectors),"
|
|
|
|
" %d cyls, %d heads, %d S/T, 512 B/S\n",
|
|
|
|
unit, l / 10, l % 10, sc->nsect, i, j, k);
|
|
|
|
|
|
|
|
if (bootverbose)
|
|
|
|
printf("fla%d: JEDEC=0x%x unitsize=%ld mediasize=%ld"
|
|
|
|
" chipsize=%ld interleave=%d window=%lx\n",
|
|
|
|
unit, sc->ds.type, sc->ds.unitSize, sc->ds.mediaSize,
|
|
|
|
sc->ds.chipSize, sc->ds.interleaving, sc->ds.window);
|
|
|
|
|
2000-04-15 05:54:02 +00:00
|
|
|
bioq_init(&sc->bio_queue);
|
1999-08-06 15:59:07 +00:00
|
|
|
|
1999-08-15 14:30:09 +00:00
|
|
|
devstat_add_entry(&softc[unit].stats, "fla", unit, DEV_BSIZE,
|
|
|
|
DEVSTAT_NO_ORDERED_TAGS,
|
Revamp the devstat priority system. All disks now have the same priority.
The same goes for CD drivers and tape drivers. In systems with mixed IDE
and SCSI, devices in the same priority class will be sorted in attach
order.
Also, the 'CCD' priority is now the 'ARRAY' priority, and a number of
drivers have been modified to use that priority.
This includes the necessary changes to all drivers, except the ATA drivers.
Soren will modify those separately.
This does not include and does not require any change in the devstat
version number, since no known userland applications use the priority
enumerations.
Reviewed by: msmith, sos, phk, jlemon, mjacob, bde
1999-12-08 04:45:23 +00:00
|
|
|
DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
|
|
|
|
DEVSTAT_PRIORITY_DISK);
|
1999-08-29 13:29:29 +00:00
|
|
|
|
1999-09-12 20:40:29 +00:00
|
|
|
sc->dev = disk_create(unit, &sc->disk, 0, &fla_cdevsw, &fladisk_cdevsw);
|
1999-08-29 13:29:29 +00:00
|
|
|
sc->dev->si_drv1 = sc;
|
|
|
|
sc->unit = unit;
|
|
|
|
|
|
|
|
return (0);
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static device_method_t fla_methods[] = {
|
|
|
|
/* Device interface */
|
|
|
|
DEVMETHOD(device_probe, flaprobe),
|
|
|
|
DEVMETHOD(device_attach, flaattach),
|
|
|
|
{0, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t fladriver = {
|
|
|
|
"fla",
|
|
|
|
fla_methods,
|
|
|
|
sizeof(struct fla_s),
|
|
|
|
};
|
|
|
|
|
|
|
|
static devclass_t fla_devclass;
|
|
|
|
|
1999-08-29 13:29:29 +00:00
|
|
|
DRIVER_MODULE(fla, isa, fladriver, fla_devclass, 0, 0);
|