Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / contrib / dev / fla / fla.c
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD: src/sys/contrib/dev/fla/fla.c,v 1.16 1999/12/08 04:45:16 ken Exp $ 
10  *
11  */
12
13 #include "fla.h"
14 #include <sys/param.h>
15 #include <sys/systm.h>
16 #include <sys/sysctl.h>
17 #include <sys/kernel.h>
18 #include <sys/buf.h>
19 #include <sys/malloc.h>
20 #include <sys/conf.h>
21 #include <sys/disk.h>
22 #include <sys/devicestat.h>
23 #include <sys/module.h>
24 #include <machine/clock.h>
25 #include <machine/resource.h>
26
27 #include <vm/vm.h>
28 #include <vm/pmap.h>
29 #include <vm/vm_param.h>
30
31 #include <sys/bus.h>
32 #include <isa/isavar.h>
33
34 #ifdef SMP
35 #include <machine/smp.h>
36 #define LEAVE() rel_mplock();                   
37 #define ENTER() get_mplock();                   
38 #else
39 #define LEAVE()
40 #define ENTER()
41 #endif
42
43 #include <contrib/dev/fla/msysosak.h>
44
45 MALLOC_DEFINE(M_FLA, "fla driver", "fla driver storage");
46
47 static int fla_debug = 0;
48 SYSCTL_INT(_debug, OID_AUTO, fladebug, CTLFLAG_RW, &fla_debug, 0, "");
49
50 #define CDEV_MAJOR      102
51 #define BDEV_MAJOR      28
52
53 static d_strategy_t flastrategy;
54 static d_open_t flaopen;
55 static d_close_t flaclose;
56 static d_ioctl_t flaioctl;
57
58 static struct cdevsw fla_cdevsw = {
59         /* open */      flaopen,
60         /* close */     flaclose,
61         /* read */      physread,
62         /* write */     physwrite,
63         /* ioctl */     flaioctl,
64         /* poll */      nopoll,
65         /* mmap */      nommap,
66         /* strategy */  flastrategy,
67         /* name */      "fla",
68         /* maj */       CDEV_MAJOR,
69         /* dump */      nodump,
70         /* psize */     nopsize,
71         /* flags */     D_DISK | D_CANFREE,
72         /* bmaj */      BDEV_MAJOR
73 };
74 static struct cdevsw fladisk_cdevsw;
75
76 void *
77 doc2k_malloc(int bytes) 
78 {
79         return malloc(bytes, M_FLA, M_WAITOK);
80 }
81
82 void
83 doc2k_free(void *ptr)
84 {
85         free(ptr, M_FLA);
86 }
87
88 void
89 doc2k_delay(unsigned msec)
90 {
91         DELAY(1000 * msec);
92 }
93
94 void
95 doc2k_memcpy(void *dst, const void *src, unsigned len)
96 {
97         bcopy(src, dst, len);
98 }
99
100 int
101 doc2k_memcmp(const void *dst, const void *src, unsigned len)
102 {
103         return (bcmp(src, dst, len));
104 }
105
106 void
107 doc2k_memset(void *dst, int c, unsigned len)
108 {
109         u_char *p = dst;
110         while (len--)
111                 *p++ = c;
112 }
113
114 static struct fla_s {
115         int busy;
116         int unit;
117         unsigned nsect;
118         struct doc2k_stat ds;
119         struct buf_queue_head buf_queue;
120         struct devstat stats;
121         struct disk disk;
122         dev_t dev;
123 } softc[NFLA];
124
125 static int
126 flaopen(dev_t dev, int flag, int fmt, struct proc *p)
127 {
128         struct fla_s *sc;
129         int error;
130         struct disklabel *dl;
131
132         if (fla_debug)
133                 printf("flaopen(%s %x %x %p)\n",
134                         devtoname(dev), flag, fmt, p);
135
136         sc = dev->si_drv1;
137
138         error = doc2k_open(sc->unit);
139
140         if (error) {
141                 printf("doc2k_open(%d) -> err %d\n", sc->unit, error);
142                 return (EIO);
143         }
144
145         dl = &sc->disk.d_label;
146         bzero(dl, sizeof(*dl));
147         error = doc2k_size(sc->unit, &dl->d_secperunit,
148             &dl->d_ncylinders, &dl->d_ntracks, &dl->d_nsectors);
149         dl->d_secsize = DEV_BSIZE;
150         dl->d_secpercyl = dl->d_ntracks * dl->d_nsectors; /* XXX */
151
152         return (0);
153 }
154
155 static int
156 flaclose(dev_t dev, int flags, int fmt, struct proc *p)
157 {
158         int error;
159         struct fla_s *sc;
160
161         if (fla_debug)
162                 printf("flaclose(%s %x %x %p)\n",
163                         devtoname(dev), flags, fmt, p);
164
165         sc = dev->si_drv1;
166
167         error = doc2k_close(sc->unit);
168         if (error) {
169                 printf("doc2k_close(%d) -> err %d\n", sc->unit, error);
170                 return (EIO);
171         }
172         return (0);
173 }
174
175 static int
176 flaioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
177 {
178
179         if (fla_debug)
180                 printf("flaioctl(%s %lx %p %x %p)\n",
181                         devtoname(dev), cmd, addr, flags, p);
182
183         return (ENOIOCTL);
184 }
185
186 static void
187 flastrategy(struct buf *bp)
188 {
189         int unit, error;
190         int s;
191         struct fla_s *sc;
192         enum doc2k_work what;
193
194         if (fla_debug > 1)
195                 printf("flastrategy(%p) %s %lx, %d, %ld, %p)\n",
196                     bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno, 
197                     bp->b_bcount / DEV_BSIZE, bp->b_data);
198
199         sc = bp->b_dev->si_drv1;
200
201         s = splbio();
202
203         bufqdisksort(&sc->buf_queue, bp);
204
205         if (sc->busy) {
206                 splx(s);
207                 return;
208         }
209
210         sc->busy++;
211         
212         while (1) {
213                 bp = bufq_first(&sc->buf_queue);
214                 if (bp)
215                         bufq_remove(&sc->buf_queue, bp);
216                 splx(s);
217                 if (!bp)
218                         break;
219
220                 devstat_start_transaction(&sc->stats);
221                 bp->b_resid = bp->b_bcount;
222                 unit = dkunit(bp->b_dev);
223
224                 if (bp->b_flags & B_FREEBUF)
225                         what = DOC2K_ERASE;
226                 else if (bp->b_flags & B_READ)
227                         what = DOC2K_READ;
228                 else 
229                         what = DOC2K_WRITE;
230
231                 LEAVE();
232
233                 error = doc2k_rwe( unit, what, bp->b_pblkno,
234                     bp->b_bcount / DEV_BSIZE, bp->b_data);
235
236                 ENTER();
237
238                 if (fla_debug > 1 || error) {
239                         printf("fla%d: %d = rwe(%p, %d, %d, %d, %ld, %p)\n",
240                             unit, error, bp, unit, what, bp->b_pblkno, 
241                             bp->b_bcount / DEV_BSIZE, bp->b_data);
242                 }
243                 if (error) {
244                         bp->b_error = EIO;
245                         bp->b_flags |= B_ERROR;
246                 } else {
247                         bp->b_resid = 0;
248                 }
249                 devstat_end_transaction_buf(&sc->stats, bp);
250                 biodone(bp);
251
252                 s = splbio();
253         }
254         sc->busy = 0;
255         return;
256 }
257
258 static int
259 flaprobe (device_t dev)
260 {
261         int unit;
262         struct fla_s *sc;
263         int i;
264
265         unit = device_get_unit(dev);
266         sc = &softc[unit];
267
268         /* This is slightly ugly */
269         i = doc2k_probe(unit, KERNBASE + 0xc0000, KERNBASE + 0xe0000);
270         if (i)
271                 return (ENXIO);
272
273         i = doc2k_info(unit, &sc->ds);
274         if (i)
275                 return (ENXIO);
276
277         bus_set_resource(dev, SYS_RES_MEMORY, 0, 
278                 sc->ds.window - KERNBASE, 8192);
279
280         return (0);
281 }
282
283 static int
284 flaattach (device_t dev)
285 {
286         int unit;
287         int i, j, k, l, m, error;
288         struct fla_s *sc;
289
290         unit = device_get_unit(dev);
291         sc = &softc[unit];
292
293         error = doc2k_open(unit);
294         if (error) {
295                 printf("doc2k_open(%d) -> err %d\n", unit, error);
296                 return (EIO);
297         }
298
299         error = doc2k_size(unit, &sc->nsect, &i, &j, &k );
300         if (error) {
301                 printf("doc2k_size(%d) -> err %d\n", unit, error);
302                 return (EIO);
303         }
304
305         printf("fla%d: <%s %s>\n", unit, sc->ds.product, sc->ds.model);
306
307         error = doc2k_close(unit);
308         if (error) {
309                 printf("doc2k_close(%d) -> err %d\n", unit, error);
310                 return (EIO);
311         }
312         
313         m = 1024L * 1024L / DEV_BSIZE;
314         l = (sc->nsect * 10 + m/2) / m;
315         printf("fla%d: %d.%01dMB (%u sectors),"
316             " %d cyls, %d heads, %d S/T, 512 B/S\n",
317             unit, l / 10, l % 10, sc->nsect, i, j, k);
318
319         if (bootverbose)
320                 printf("fla%d: JEDEC=0x%x unitsize=%ld mediasize=%ld"
321                        " chipsize=%ld interleave=%d window=%lx\n", 
322                     unit, sc->ds.type, sc->ds.unitSize, sc->ds.mediaSize, 
323                     sc->ds.chipSize, sc->ds.interleaving, sc->ds.window);
324
325         bufq_init(&sc->buf_queue);
326
327         devstat_add_entry(&softc[unit].stats, "fla", unit, DEV_BSIZE,
328                 DEVSTAT_NO_ORDERED_TAGS, 
329                 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
330                 DEVSTAT_PRIORITY_DISK);
331
332         sc->dev = disk_create(unit, &sc->disk, 0, &fla_cdevsw, &fladisk_cdevsw);
333         sc->dev->si_drv1 = sc;
334         sc->unit = unit;
335
336         return (0);
337 }
338
339 static device_method_t fla_methods[] = {
340         /* Device interface */
341         DEVMETHOD(device_probe,         flaprobe),
342         DEVMETHOD(device_attach,        flaattach),
343         {0, 0}
344 };
345
346 static driver_t fladriver = {
347         "fla",
348         fla_methods,
349         sizeof(struct fla_s),
350 };
351
352 static devclass_t       fla_devclass;
353
354 DRIVER_MODULE(fla, isa, fladriver, fla_devclass, 0, 0);