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