Merge from vendor branch OPENSSL:
[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.14 2006/09/05 00:55:36 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 dev_ops fla_ops = {
64         { "fla", CDEV_MAJOR, D_DISK | D_CANFREE },
65         .d_open =       flaopen,
66         .d_close =      flaclose,
67         .d_read =       physread,
68         .d_write =      physwrite,
69         .d_ioctl =      flaioctl,
70         .d_strategy =   flastrategy,
71 };
72
73 void *
74 doc2k_malloc(int bytes) 
75 {
76         return kmalloc(bytes, M_FLA, M_WAITOK);
77 }
78
79 void
80 doc2k_free(void *ptr)
81 {
82         kfree(ptr, M_FLA);
83 }
84
85 void
86 doc2k_delay(unsigned msec)
87 {
88         DELAY(1000 * msec);
89 }
90
91 void
92 doc2k_memcpy(void *dst, const void *src, unsigned len)
93 {
94         bcopy(src, dst, len);
95 }
96
97 int
98 doc2k_memcmp(const void *dst, const void *src, unsigned len)
99 {
100         return (bcmp(src, dst, len));
101 }
102
103 void
104 doc2k_memset(void *dst, int c, unsigned len)
105 {
106         u_char *p = dst;
107         while (len--)
108                 *p++ = c;
109 }
110
111 static struct fla_s {
112         int busy;
113         int unit;
114         unsigned nsect;
115         struct doc2k_stat ds;
116         struct bio_queue_head bio_queue;
117         struct devstat stats;
118         struct disk disk;
119         dev_t dev;
120 } softc[NFLA];
121
122 static int
123 flaopen(struct dev_open_args *ap)
124 {
125         dev_t dev = ap->a_head.a_dev;
126         struct fla_s *sc;
127         int error;
128         struct disklabel *dl;
129
130         if (fla_debug)
131                 printf("flaopen(%s %x %x)\n",
132                         devtoname(dev), ap->a_oflags, ap->a_devtype);
133
134         sc = dev->si_drv1;
135
136         error = doc2k_open(sc->unit);
137
138         if (error) {
139                 printf("doc2k_open(%d) -> err %d\n", sc->unit, error);
140                 return (EIO);
141         }
142
143         dl = &sc->disk.d_label;
144         bzero(dl, sizeof(*dl));
145         error = doc2k_size(sc->unit, &dl->d_secperunit,
146             &dl->d_ncylinders, &dl->d_ntracks, &dl->d_nsectors);
147         dl->d_secsize = DEV_BSIZE;
148         dl->d_secpercyl = dl->d_ntracks * dl->d_nsectors; /* XXX */
149
150         return (0);
151 }
152
153 static int
154 flaclose(struct dev_close_args *ap)
155 {
156         dev_t dev = ap->a_head.a_dev;
157         int error;
158         struct fla_s *sc;
159
160         if (fla_debug)
161                 printf("flaclose(%s %x %x)\n",
162                         devtoname(dev), ap->a_fflag, ap->a_devtype);
163
164         sc = dev->si_drv1;
165
166         error = doc2k_close(sc->unit);
167         if (error) {
168                 printf("doc2k_close(%d) -> err %d\n", sc->unit, error);
169                 return (EIO);
170         }
171         return (0);
172 }
173
174 static int
175 flaioctl(struct dev_ioctl_args *ap)
176 {
177         dev_t dev = ap->a_head.a_dev;
178
179         if (fla_debug)
180                 printf("flaioctl(%s %lx %p %x)\n",
181                         devtoname(dev), ap->a_cmd, ap->a_data, ap->a_fflag);
182
183         return (ENOIOCTL);
184 }
185
186 static int
187 flastrategy(struct dev_strategy_args *ap)
188 {
189         dev_t dev = ap->a_head.a_dev;
190         struct bio *bio = ap->a_bio;
191         struct buf *bp = bio->bio_buf;
192         int unit, error;
193         struct fla_s *sc;
194         enum doc2k_work what;
195
196         if (fla_debug > 1) {
197                 printf("flastrategy(%p) %s %x, %lld, %d, %p)\n",
198                         bp, devtoname(dev), bp->b_flags, bio->bio_offset, 
199                         bp->b_bcount, bp->b_data);
200         }
201
202         sc = dev->si_drv1;
203         bio->bio_driver_info = dev;
204         crit_enter();
205         bioqdisksort(&sc->bio_queue, bio);
206         if (sc->busy) {
207                 crit_exit();
208                 return(0);
209         }
210         sc->busy++;
211         
212         while (1) {
213                 bio = bioq_first(&sc->bio_queue);
214                 if (bio == NULL) {
215                         crit_exit();
216                         break;
217                 }
218                 bioq_remove(&sc->bio_queue, bio);
219                 bp = bio->bio_buf;
220                 dev = bio->bio_driver_info;
221
222                 devstat_start_transaction(&sc->stats);
223                 bp->b_resid = bp->b_bcount;
224                 unit = dkunit(dev);
225
226                 switch(bp->b_cmd) {
227                 case BUF_CMD_FREEBLKS:
228                         what = DOC2K_ERASE;
229                         break;
230                 case BUF_CMD_READ:
231                         what = DOC2K_READ;
232                         break;
233                 case BUF_CMD_WRITE:
234                         what = DOC2K_WRITE;
235                         break;
236                 default:
237                         panic("fla: bad b_cmd %d", bp->b_cmd);
238                 }
239
240                 LEAVE();
241
242                 error = doc2k_rwe(unit, what,
243                                   (unsigned)(bio->bio_offset >> DEV_BSHIFT),
244                                   bp->b_bcount / DEV_BSIZE, bp->b_data);
245
246                 ENTER();
247
248                 if (fla_debug > 1 || error) {
249                         printf("fla%d: %d = rwe(%p, %d, %d, %lld, %d, %p)\n",
250                             unit, error, bp, unit, what, bio->bio_offset, 
251                             bp->b_bcount, bp->b_data);
252                 }
253                 if (error) {
254                         bp->b_error = EIO;
255                         bp->b_flags |= B_ERROR;
256                 } else {
257                         bp->b_resid = 0;
258                 }
259                 devstat_end_transaction_buf(&sc->stats, bp);
260                 biodone(bio);
261
262                 crit_enter();
263         }
264         sc->busy = 0;
265         return(0);
266 }
267
268 static int
269 flaprobe (device_t dev)
270 {
271         int unit;
272         struct fla_s *sc;
273         int i;
274
275         unit = device_get_unit(dev);
276         sc = &softc[unit];
277
278         /* This is slightly ugly */
279         i = doc2k_probe(unit, KERNBASE + 0xc0000, KERNBASE + 0xe0000);
280         if (i)
281                 return (ENXIO);
282
283         i = doc2k_info(unit, &sc->ds);
284         if (i)
285                 return (ENXIO);
286
287         bus_set_resource(dev, SYS_RES_MEMORY, 0, 
288                 sc->ds.window - KERNBASE, 8192);
289
290         return (0);
291 }
292
293 static int
294 flaattach (device_t dev)
295 {
296         int unit;
297         int i, j, k, l, m, error;
298         struct fla_s *sc;
299
300         unit = device_get_unit(dev);
301         sc = &softc[unit];
302
303         error = doc2k_open(unit);
304         if (error) {
305                 printf("doc2k_open(%d) -> err %d\n", unit, error);
306                 return (EIO);
307         }
308
309         error = doc2k_size(unit, &sc->nsect, &i, &j, &k );
310         if (error) {
311                 printf("doc2k_size(%d) -> err %d\n", unit, error);
312                 return (EIO);
313         }
314
315         printf("fla%d: <%s %s>\n", unit, sc->ds.product, sc->ds.model);
316
317         error = doc2k_close(unit);
318         if (error) {
319                 printf("doc2k_close(%d) -> err %d\n", unit, error);
320                 return (EIO);
321         }
322         
323         m = 1024L * 1024L / DEV_BSIZE;
324         l = (sc->nsect * 10 + m/2) / m;
325         printf("fla%d: %d.%01dMB (%u sectors),"
326             " %d cyls, %d heads, %d S/T, 512 B/S\n",
327             unit, l / 10, l % 10, sc->nsect, i, j, k);
328
329         if (bootverbose)
330                 printf("fla%d: JEDEC=0x%x unitsize=%ld mediasize=%ld"
331                        " chipsize=%ld interleave=%d window=%lx\n", 
332                     unit, sc->ds.type, sc->ds.unitSize, sc->ds.mediaSize, 
333                     sc->ds.chipSize, sc->ds.interleaving, sc->ds.window);
334
335         bioq_init(&sc->bio_queue);
336
337         devstat_add_entry(&softc[unit].stats, "fla", unit, DEV_BSIZE,
338                 DEVSTAT_NO_ORDERED_TAGS, 
339                 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
340                 DEVSTAT_PRIORITY_DISK);
341
342         sc->dev = disk_create(unit, &sc->disk, 0, &fla_ops);
343         sc->dev->si_drv1 = sc;
344         sc->unit = unit;
345
346         return (0);
347 }
348
349 static device_method_t fla_methods[] = {
350         /* Device interface */
351         DEVMETHOD(device_probe,         flaprobe),
352         DEVMETHOD(device_attach,        flaattach),
353         {0, 0}
354 };
355
356 static driver_t fladriver = {
357         "fla",
358         fla_methods,
359         sizeof(struct fla_s),
360 };
361
362 static devclass_t       fla_devclass;
363
364 DRIVER_MODULE(fla, isa, fladriver, fla_devclass, 0, 0);