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-06 15:59:07 +00:00
|
|
|
#include <sys/module.h>
|
|
|
|
#include <machine/resource.h>
|
2003-04-01 15:06:26 +00:00
|
|
|
#include <geom/geom_disk.h>
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
void *
|
|
|
|
doc2k_malloc(int bytes)
|
|
|
|
{
|
2003-02-19 05:47:46 +00:00
|
|
|
return malloc(bytes, M_FLA, M_WAITOK);
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2004-02-18 21:36:53 +00:00
|
|
|
struct disk *disk;
|
1999-08-29 13:29:29 +00:00
|
|
|
dev_t dev;
|
2000-04-23 09:10:09 +00:00
|
|
|
} softc[8];
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
static int
|
2003-02-22 09:32:57 +00:00
|
|
|
flaopen(struct disk *dp)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
|
|
|
struct fla_s *sc;
|
|
|
|
int error;
|
2002-09-20 19:36:05 +00:00
|
|
|
u_int spu, ncyl, nt, ns;
|
1999-08-06 15:59:07 +00:00
|
|
|
|
2003-02-22 09:32:57 +00:00
|
|
|
sc = dp->d_drv1;
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
error = doc2k_open(sc->unit);
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
printf("doc2k_open(%d) -> err %d\n", sc->unit, error);
|
|
|
|
return (EIO);
|
|
|
|
}
|
|
|
|
|
2002-09-20 19:36:05 +00:00
|
|
|
error = doc2k_size(sc->unit, &spu, &ncyl, &nt, &ns);
|
2004-02-18 21:36:53 +00:00
|
|
|
sc->disk->d_sectorsize = DEV_BSIZE;
|
|
|
|
sc->disk->d_mediasize = (off_t)spu * DEV_BSIZE;
|
|
|
|
sc->disk->d_fwsectors = ns;
|
|
|
|
sc->disk->d_fwheads = nt;
|
1999-08-29 13:29:29 +00:00
|
|
|
|
1999-08-14 11:40:51 +00:00
|
|
|
return (0);
|
1999-08-06 15:59:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-02-22 09:32:57 +00:00
|
|
|
flaclose(struct disk *dp)
|
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;
|
|
|
|
|
2003-02-22 09:32:57 +00:00
|
|
|
sc = dp->d_drv1;
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
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 void
|
2000-04-15 05:54:02 +00:00
|
|
|
flastrategy(struct bio *bp)
|
1999-08-06 15:59:07 +00:00
|
|
|
{
|
|
|
|
int unit, error;
|
|
|
|
struct fla_s *sc;
|
|
|
|
enum doc2k_work what;
|
|
|
|
|
2003-02-22 09:32:57 +00:00
|
|
|
sc = bp->bio_disk->d_drv1;
|
1999-08-06 15:59:07 +00:00
|
|
|
|
|
|
|
|
2003-04-01 15:06:26 +00:00
|
|
|
bioq_disksort(&sc->bio_queue, bp);
|
1999-08-06 15:59:07 +00:00
|
|
|
|
1999-08-15 14:30:09 +00:00
|
|
|
if (sc->busy) {
|
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-06 15:59:07 +00:00
|
|
|
if (!bp)
|
|
|
|
break;
|
|
|
|
|
2000-04-15 05:54:02 +00:00
|
|
|
bp->bio_resid = bp->bio_bcount;
|
2002-09-20 16:26:12 +00:00
|
|
|
unit = sc->unit;
|
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
|
|
|
|
2003-02-22 09:32:57 +00:00
|
|
|
if (error) {
|
|
|
|
printf("fla%d: %d = rwe(%p, %d, %d, %jd, %ld, %p)\n",
|
2002-03-19 20:46:30 +00:00
|
|
|
unit, error, bp, unit, what,
|
2003-02-22 09:32:57 +00:00
|
|
|
(intmax_t)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
|
|
|
}
|
2003-03-08 08:01:31 +00:00
|
|
|
biodone(bp);
|
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
|
|
|
|
2004-02-18 21:36:53 +00:00
|
|
|
sc->disk = disk_alloc();
|
|
|
|
sc->disk->d_open = flaopen;
|
|
|
|
sc->disk->d_close = flaclose;
|
|
|
|
sc->disk->d_strategy = flastrategy;
|
|
|
|
sc->disk->d_drv1 = sc;
|
|
|
|
sc->disk->d_name = "fla";
|
|
|
|
sc->disk->d_maxsize = MAXPHYS;
|
1999-08-29 13:29:29 +00:00
|
|
|
sc->unit = unit;
|
2004-02-18 21:36:53 +00:00
|
|
|
sc->disk->d_unit = unit;
|
|
|
|
sc->disk->d_flags = DISKFLAG_CANDELETE | DISKFLAG_NEEDSGIANT;
|
|
|
|
disk_create(sc->disk, DISK_VERSION);
|
1999-08-29 13:29:29 +00:00
|
|
|
|
|
|
|
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);
|