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