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