mlcd.c revision 1.1 1 1.1 itohy /* $NetBSD: mlcd.c,v 1.1 2002/11/15 14:10:51 itohy Exp $ */
2 1.1 itohy
3 1.1 itohy /*-
4 1.1 itohy * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 1.1 itohy * All rights reserved.
6 1.1 itohy *
7 1.1 itohy * This code is derived from software contributed to The NetBSD Foundation
8 1.1 itohy * by ITOH Yasufumi.
9 1.1 itohy *
10 1.1 itohy * Redistribution and use in source and binary forms, with or without
11 1.1 itohy * modification, are permitted provided that the following conditions
12 1.1 itohy * are met:
13 1.1 itohy * 1. Redistributions of source code must retain the above copyright
14 1.1 itohy * notice, this list of conditions and the following disclaimer.
15 1.1 itohy * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 itohy * notice, this list of conditions and the following disclaimer in the
17 1.1 itohy * documentation and/or other materials provided with the distribution.
18 1.1 itohy * 3. All advertising materials mentioning features or use of this software
19 1.1 itohy * must display the following acknowledgement:
20 1.1 itohy * This product includes software developed by the NetBSD
21 1.1 itohy * Foundation, Inc. and its contributors.
22 1.1 itohy * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 itohy * contributors may be used to endorse or promote products derived
24 1.1 itohy * from this software without specific prior written permission.
25 1.1 itohy *
26 1.1 itohy * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 itohy * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 itohy * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 itohy * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 itohy * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 itohy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 itohy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 itohy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 itohy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 itohy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 itohy * POSSIBILITY OF SUCH DAMAGE.
37 1.1 itohy */
38 1.1 itohy
39 1.1 itohy #include <sys/param.h>
40 1.1 itohy #include <sys/buf.h>
41 1.1 itohy #include <sys/device.h>
42 1.1 itohy #include <sys/kernel.h>
43 1.1 itohy #include <sys/malloc.h>
44 1.1 itohy #include <sys/proc.h>
45 1.1 itohy #include <sys/systm.h>
46 1.1 itohy #include <sys/vnode.h>
47 1.1 itohy #include <sys/conf.h>
48 1.1 itohy
49 1.1 itohy #include <dreamcast/dev/maple/maple.h>
50 1.1 itohy #include <dreamcast/dev/maple/mapleconf.h>
51 1.1 itohy
52 1.1 itohy #define MLCD_MAXACCSIZE 1012 /* (255*4) - 8 = 253*32 / 8 */
53 1.1 itohy
54 1.1 itohy struct mlcd_funcdef { /* XXX assuming little-endian structure packing */
55 1.1 itohy unsigned unused : 6,
56 1.1 itohy bw : 1, /* 0: normally white, 1: normally black */
57 1.1 itohy hv : 1, /* 0: horizontal, 1: vertical */
58 1.1 itohy ra : 4, /* 0 */
59 1.1 itohy wa : 4, /* number of access / write */
60 1.1 itohy bb : 8, /* block size / 32 - 1 */
61 1.1 itohy pt : 8; /* number of partition - 1 */
62 1.1 itohy };
63 1.1 itohy
64 1.1 itohy struct mlcd_request_write_data {
65 1.1 itohy u_int32_t func_code;
66 1.1 itohy u_int8_t pt;
67 1.1 itohy u_int8_t phase; /* 0, 1, 2, 3: for each 128 byte */
68 1.1 itohy u_int16_t block;
69 1.1 itohy u_int8_t data[MLCD_MAXACCSIZE];
70 1.1 itohy };
71 1.1 itohy #define MLCD_SIZE_REQW(sc) ((sc)->sc_waccsz + 8)
72 1.1 itohy
73 1.1 itohy struct mlcd_request_get_media_info {
74 1.1 itohy u_int32_t func_code;
75 1.1 itohy u_int32_t pt; /* pt (1 byte) and unused 3 bytes */
76 1.1 itohy };
77 1.1 itohy
78 1.1 itohy struct mlcd_media_info {
79 1.1 itohy u_int8_t width; /* width - 1 */
80 1.1 itohy u_int8_t height; /* height - 1 */
81 1.1 itohy u_int8_t rsvd[2]; /* ? 0x10 0x02 */
82 1.1 itohy };
83 1.1 itohy
84 1.1 itohy struct mlcd_response_media_info {
85 1.1 itohy u_int32_t func_code; /* function code (big endian) */
86 1.1 itohy struct mlcd_media_info info;
87 1.1 itohy };
88 1.1 itohy
89 1.1 itohy struct mlcd_softc {
90 1.1 itohy struct device sc_dev;
91 1.1 itohy
92 1.1 itohy struct device *sc_parent;
93 1.1 itohy struct maple_unit *sc_unit;
94 1.1 itohy enum mlcd_stat {
95 1.1 itohy MLCD_INIT, /* during initialization */
96 1.1 itohy MLCD_INIT2, /* during initialization */
97 1.1 itohy MLCD_IDLE, /* init done, not in I/O */
98 1.1 itohy MLCD_WRITE, /* in write operation */
99 1.1 itohy MLCD_DETACH /* detaching */
100 1.1 itohy } sc_stat;
101 1.1 itohy
102 1.1 itohy int sc_npt; /* number of partitions */
103 1.1 itohy int sc_bsize; /* block size */
104 1.1 itohy int sc_wacc; /* number of write access per block */
105 1.1 itohy int sc_waccsz; /* size of a write access */
106 1.1 itohy
107 1.1 itohy struct mlcd_pt {
108 1.1 itohy int pt_flags;
109 1.1 itohy #define MLCD_PT_OK 1 /* partition is alive */
110 1.1 itohy #define MLCD_PT_OPEN 2
111 1.1 itohy struct mlcd_media_info pt_info; /* geometry per part */
112 1.1 itohy int pt_size; /* partition size in byte */
113 1.1 itohy int pt_nblk; /* partition size on block */
114 1.1 itohy
115 1.1 itohy char pt_name[16 /* see device.h */ + 4 /* ".256" */];
116 1.1 itohy } *sc_pt;
117 1.1 itohy
118 1.1 itohy /* write request buffer (only one is used at a time) */
119 1.1 itohy union {
120 1.1 itohy struct mlcd_request_write_data req_write;
121 1.1 itohy struct mlcd_request_get_media_info req_minfo;
122 1.1 itohy } sc_req;
123 1.1 itohy #define sc_reqw sc_req.req_write
124 1.1 itohy #define sc_reqm sc_req.req_minfo
125 1.1 itohy
126 1.1 itohy /* pending buffers */
127 1.1 itohy struct bufq_state sc_q;
128 1.1 itohy
129 1.1 itohy /* current I/O access */
130 1.1 itohy struct buf *sc_bp;
131 1.1 itohy int sc_retry;
132 1.1 itohy #define MLCD_MAXRETRY 10
133 1.1 itohy };
134 1.1 itohy
135 1.1 itohy /*
136 1.1 itohy * minor number layout (mlcddetach() depends on this layout):
137 1.1 itohy *
138 1.1 itohy * 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
139 1.1 itohy * |---------------------------------| |---------------------|
140 1.1 itohy * unit part
141 1.1 itohy */
142 1.1 itohy #define MLCD_PART(dev) (minor(dev) & 0xff)
143 1.1 itohy #define MLCD_UNIT(dev) (minor(dev) >> 8)
144 1.1 itohy #define MLCD_MINOR(unit, part) (((unit) << 8) | (part))
145 1.1 itohy
146 1.1 itohy static int mlcdmatch __P((struct device *, struct cfdata *, void *));
147 1.1 itohy static void mlcdattach __P((struct device *, struct device *, void *));
148 1.1 itohy static int mlcddetach __P((struct device *, int));
149 1.1 itohy static void mlcd_intr __P((void *, struct maple_response *, int, int));
150 1.1 itohy static void mlcd_printerror __P((const char *, u_int32_t));
151 1.1 itohy static void mlcdstart __P((struct mlcd_softc *));
152 1.1 itohy static void mlcdstart_bp __P((struct mlcd_softc *, struct buf *bp));
153 1.1 itohy static void mlcddone __P((struct mlcd_softc *));
154 1.1 itohy
155 1.1 itohy dev_type_open(mlcdopen);
156 1.1 itohy dev_type_close(mlcdclose);
157 1.1 itohy dev_type_write(mlcdwrite);
158 1.1 itohy dev_type_ioctl(mlcdioctl);
159 1.1 itohy dev_type_strategy(mlcdstrategy);
160 1.1 itohy
161 1.1 itohy const struct cdevsw mlcd_cdevsw = {
162 1.1 itohy mlcdopen, mlcdclose, noread, mlcdwrite, mlcdioctl,
163 1.1 itohy nostop, notty, nopoll, nommap, nokqfilter
164 1.1 itohy };
165 1.1 itohy
166 1.1 itohy CFATTACH_DECL(mlcd, sizeof(struct mlcd_softc),
167 1.1 itohy mlcdmatch, mlcdattach, mlcddetach, NULL);
168 1.1 itohy
169 1.1 itohy extern struct cfdriver mlcd_cd;
170 1.1 itohy
171 1.1 itohy /* initial image "NetBSD dreamcast" */
172 1.1 itohy static const char initimg48x32[192] = {
173 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xac, 0xe5, 0x56, 0x70, 0xb8,
179 1.1 itohy 0x14, 0x12, 0x15, 0x49, 0x08, 0xa4, 0x13, 0x1c, 0x15, 0x4e, 0x78, 0xa4,
180 1.1 itohy 0x10, 0x90, 0x15, 0x48, 0x49, 0xa4, 0x7b, 0x0c, 0xe3, 0xc6, 0x36, 0xb8,
181 1.1 itohy 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
182 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 1.1 itohy 0x07, 0xcf, 0x9f, 0xb8, 0x79, 0x8e, 0x19, 0x99, 0xb3, 0x6c, 0x8d, 0x8c,
184 1.1 itohy 0x31, 0xb1, 0x63, 0x4c, 0x0d, 0x8c, 0x31, 0xb0, 0x66, 0x18, 0x3b, 0x58,
185 1.1 itohy 0x63, 0x18, 0x66, 0x19, 0xdb, 0x58, 0x63, 0x0c, 0x3e, 0x7d, 0x93, 0x58,
186 1.1 itohy 0x63, 0x06, 0x46, 0x30, 0xe3, 0x78, 0x66, 0x66, 0xcc, 0x30, 0x06, 0x30,
187 1.1 itohy 0x36, 0x64, 0xcc, 0x00, 0x06, 0x30, 0x0f, 0x38, 0x7e, 0x00, 0x0e, 0x38,
188 1.1 itohy 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
189 1.1 itohy };
190 1.1 itohy
191 1.1 itohy static int
192 1.1 itohy mlcdmatch(parent, cf, aux)
193 1.1 itohy struct device *parent;
194 1.1 itohy struct cfdata *cf;
195 1.1 itohy void *aux;
196 1.1 itohy {
197 1.1 itohy struct maple_attach_args *ma = aux;
198 1.1 itohy
199 1.1 itohy return (ma->ma_function == MAPLE_FN_LCD ? MAPLE_MATCH_FUNC : 0);
200 1.1 itohy }
201 1.1 itohy
202 1.1 itohy static void
203 1.1 itohy mlcdattach(parent, self, aux)
204 1.1 itohy struct device *parent, *self;
205 1.1 itohy void *aux;
206 1.1 itohy {
207 1.1 itohy struct mlcd_softc *sc = (void *) self;
208 1.1 itohy struct maple_attach_args *ma = aux;
209 1.1 itohy int i;
210 1.1 itohy union {
211 1.1 itohy u_int32_t v;
212 1.1 itohy struct mlcd_funcdef s;
213 1.1 itohy } funcdef;
214 1.1 itohy
215 1.1 itohy sc->sc_parent = parent;
216 1.1 itohy sc->sc_unit = ma->ma_unit;
217 1.1 itohy
218 1.1 itohy funcdef.v = maple_get_function_data(ma->ma_devinfo, MAPLE_FN_LCD);
219 1.1 itohy printf(": LCD display\n");
220 1.1 itohy printf("%s: %d LCD, %d bytes/block, ",
221 1.1 itohy sc->sc_dev.dv_xname,
222 1.1 itohy sc->sc_npt = funcdef.s.pt + 1,
223 1.1 itohy sc->sc_bsize = (funcdef.s.bb + 1) << 5);
224 1.1 itohy if ((sc->sc_wacc = funcdef.s.wa) == 0)
225 1.1 itohy printf("no ");
226 1.1 itohy else
227 1.1 itohy printf("%d acc/", sc->sc_wacc);
228 1.1 itohy printf("write, %s, normally %s\n",
229 1.1 itohy funcdef.s.hv ? "vertical" : "horizontal",
230 1.1 itohy funcdef.s.bw ? "black" : "white");
231 1.1 itohy
232 1.1 itohy /*
233 1.1 itohy * start init sequence
234 1.1 itohy */
235 1.1 itohy sc->sc_stat = MLCD_INIT;
236 1.1 itohy bufq_alloc(&sc->sc_q, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK);
237 1.1 itohy
238 1.1 itohy /* check consistency */
239 1.1 itohy if (sc->sc_wacc != 0) {
240 1.1 itohy sc->sc_waccsz = sc->sc_bsize / sc->sc_wacc;
241 1.1 itohy if (sc->sc_bsize != sc->sc_waccsz * sc->sc_wacc) {
242 1.1 itohy printf("%s: write access isn't equally divided\n",
243 1.1 itohy sc->sc_dev.dv_xname);
244 1.1 itohy sc->sc_wacc = 0; /* no write */
245 1.1 itohy } else if (sc->sc_waccsz > MLCD_MAXACCSIZE) {
246 1.1 itohy printf("%s: write access size is too large\n",
247 1.1 itohy sc->sc_dev.dv_xname);
248 1.1 itohy sc->sc_wacc = 0; /* no write */
249 1.1 itohy }
250 1.1 itohy }
251 1.1 itohy if (sc->sc_wacc == 0) {
252 1.1 itohy printf("%s: device doesn't support write\n",
253 1.1 itohy sc->sc_dev.dv_xname);
254 1.1 itohy return;
255 1.1 itohy }
256 1.1 itohy
257 1.1 itohy /* per-part structure */
258 1.1 itohy sc->sc_pt = malloc(sizeof(struct mlcd_pt) * sc->sc_npt, M_DEVBUF,
259 1.1 itohy M_WAITOK|M_ZERO);
260 1.1 itohy
261 1.1 itohy for (i = 0; i < sc->sc_npt; i++) {
262 1.1 itohy sprintf(sc->sc_pt[i].pt_name, "%s.%d", sc->sc_dev.dv_xname, i);
263 1.1 itohy }
264 1.1 itohy
265 1.1 itohy maple_set_callback(parent, sc->sc_unit, MAPLE_FN_LCD,
266 1.1 itohy mlcd_intr, sc);
267 1.1 itohy
268 1.1 itohy /*
269 1.1 itohy * get size (start from partition 0)
270 1.1 itohy */
271 1.1 itohy sc->sc_reqm.func_code = htonl(MAPLE_FUNC(MAPLE_FN_LCD));
272 1.1 itohy sc->sc_reqm.pt = 0;
273 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, MAPLE_FN_LCD,
274 1.1 itohy MAPLE_COMMAND_GETMINFO, sizeof sc->sc_reqm / 4, &sc->sc_reqm, 0);
275 1.1 itohy }
276 1.1 itohy
277 1.1 itohy static int
278 1.1 itohy mlcddetach(self, flags)
279 1.1 itohy struct device *self;
280 1.1 itohy int flags;
281 1.1 itohy {
282 1.1 itohy struct mlcd_softc *sc = (struct mlcd_softc *) self;
283 1.1 itohy struct buf *bp;
284 1.1 itohy int minor_l, minor_h;
285 1.1 itohy
286 1.1 itohy sc->sc_stat = MLCD_DETACH; /* just in case */
287 1.1 itohy
288 1.1 itohy /*
289 1.1 itohy * kill pending I/O
290 1.1 itohy */
291 1.1 itohy if ((bp = sc->sc_bp) != NULL) {
292 1.1 itohy bp->b_error = EIO;
293 1.1 itohy bp->b_flags |= B_ERROR;
294 1.1 itohy bp->b_resid = bp->b_bcount;
295 1.1 itohy biodone(bp);
296 1.1 itohy }
297 1.1 itohy while ((bp = BUFQ_GET(&sc->sc_q)) != NULL) {
298 1.1 itohy bp->b_error = EIO;
299 1.1 itohy bp->b_flags |= B_ERROR;
300 1.1 itohy bp->b_resid = bp->b_bcount;
301 1.1 itohy biodone(bp);
302 1.1 itohy }
303 1.1 itohy bufq_free(&sc->sc_q);
304 1.1 itohy
305 1.1 itohy /*
306 1.1 itohy * revoke vnodes
307 1.1 itohy */
308 1.1 itohy minor_l = MLCD_MINOR(self->dv_unit, 0);
309 1.1 itohy minor_h = MLCD_MINOR(self->dv_unit, sc->sc_npt - 1);
310 1.1 itohy vdevgone(cdevsw_lookup_major(&mlcd_cdevsw), minor_l, minor_h, VCHR);
311 1.1 itohy
312 1.1 itohy /*
313 1.1 itohy * free per-partition structure
314 1.1 itohy */
315 1.1 itohy if (sc->sc_pt)
316 1.1 itohy free(sc->sc_pt, M_DEVBUF);
317 1.1 itohy
318 1.1 itohy return 0;
319 1.1 itohy }
320 1.1 itohy
321 1.1 itohy /*
322 1.1 itohy * called back from maple bus driver
323 1.1 itohy */
324 1.1 itohy static void
325 1.1 itohy mlcd_intr(dev, response, sz, flags)
326 1.1 itohy void *dev;
327 1.1 itohy struct maple_response *response;
328 1.1 itohy int sz, flags;
329 1.1 itohy {
330 1.1 itohy struct mlcd_softc *sc = dev;
331 1.1 itohy struct mlcd_response_media_info *rm = (void *) response->data;
332 1.1 itohy struct buf *bp;
333 1.1 itohy int part;
334 1.1 itohy struct mlcd_pt *pt;
335 1.1 itohy
336 1.1 itohy switch (sc->sc_stat) {
337 1.1 itohy case MLCD_INIT:
338 1.1 itohy /* checking part geometry */
339 1.1 itohy part = sc->sc_reqm.pt;
340 1.1 itohy pt = &sc->sc_pt[part];
341 1.1 itohy switch ((maple_response_t) response->response_code) {
342 1.1 itohy case MAPLE_RESPONSE_DATATRF:
343 1.1 itohy pt->pt_info = rm->info;
344 1.1 itohy pt->pt_size = ((pt->pt_info.width + 1) *
345 1.1 itohy (pt->pt_info.height + 1) + 7) / 8;
346 1.1 itohy pt->pt_nblk = pt->pt_size / sc->sc_bsize;
347 1.1 itohy printf("%s: %dx%d display, %d bytes\n",
348 1.1 itohy pt->pt_name,
349 1.1 itohy pt->pt_info.width + 1, pt->pt_info.height + 1,
350 1.1 itohy pt->pt_size);
351 1.1 itohy
352 1.1 itohy /* this partition is active */
353 1.1 itohy pt->pt_flags = MLCD_PT_OK;
354 1.1 itohy
355 1.1 itohy break;
356 1.1 itohy default:
357 1.1 itohy printf("%s: init: unexpected response %#x, sz %d\n",
358 1.1 itohy pt->pt_name, ntohl(response->response_code), sz);
359 1.1 itohy break;
360 1.1 itohy }
361 1.1 itohy if (++part == sc->sc_npt) {
362 1.1 itohy /* init done */
363 1.1 itohy
364 1.1 itohy /* XXX initial image for Visual Memory */
365 1.1 itohy if (sc->sc_pt[0].pt_size == sizeof initimg48x32 &&
366 1.1 itohy sc->sc_waccsz == sizeof initimg48x32 &&
367 1.1 itohy sc->sc_wacc == 1) {
368 1.1 itohy sc->sc_stat = MLCD_INIT2;
369 1.1 itohy sc->sc_reqw.func_code =
370 1.1 itohy htonl(MAPLE_FUNC(MAPLE_FN_LCD));
371 1.1 itohy sc->sc_reqw.pt = 0; /* part 0 */
372 1.1 itohy sc->sc_reqw.block = 0;
373 1.1 itohy sc->sc_reqw.phase = 0;
374 1.1 itohy bcopy(initimg48x32, sc->sc_reqw.data,
375 1.1 itohy sizeof initimg48x32);
376 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit,
377 1.1 itohy MAPLE_FN_LCD, MAPLE_COMMAND_BWRITE,
378 1.1 itohy MLCD_SIZE_REQW(sc) / 4, &sc->sc_reqw, 0);
379 1.1 itohy } else
380 1.1 itohy sc->sc_stat = MLCD_IDLE; /* init done */
381 1.1 itohy } else {
382 1.1 itohy sc->sc_reqm.pt = part;
383 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit,
384 1.1 itohy MAPLE_FN_LCD, MAPLE_COMMAND_GETMINFO,
385 1.1 itohy sizeof sc->sc_reqm / 4, &sc->sc_reqm, 0);
386 1.1 itohy }
387 1.1 itohy break;
388 1.1 itohy
389 1.1 itohy case MLCD_INIT2:
390 1.1 itohy sc->sc_stat = MLCD_IDLE; /* init done */
391 1.1 itohy break;
392 1.1 itohy
393 1.1 itohy case MLCD_WRITE:
394 1.1 itohy bp = sc->sc_bp;
395 1.1 itohy
396 1.1 itohy switch ((maple_response_t) response->response_code) {
397 1.1 itohy case MAPLE_RESPONSE_OK: /* write done */
398 1.1 itohy if (++sc->sc_reqw.phase == sc->sc_wacc) {
399 1.1 itohy /* all phase done */
400 1.1 itohy mlcddone(sc);
401 1.1 itohy } else {
402 1.1 itohy /* go next phase */
403 1.1 itohy bcopy(bp->b_data
404 1.1 itohy + sc->sc_waccsz * sc->sc_reqw.phase,
405 1.1 itohy sc->sc_reqw.data, sc->sc_waccsz);
406 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit,
407 1.1 itohy MAPLE_FN_LCD, MAPLE_COMMAND_BWRITE,
408 1.1 itohy MLCD_SIZE_REQW(sc) / 4, &sc->sc_reqw, 0);
409 1.1 itohy }
410 1.1 itohy break;
411 1.1 itohy case MAPLE_RESPONSE_LCDERR:
412 1.1 itohy mlcd_printerror(sc->sc_pt[sc->sc_reqw.pt].pt_name,
413 1.1 itohy rm->func_code /* XXX */);
414 1.1 itohy mlcdstart_bp(sc, bp); /* retry */
415 1.1 itohy break;
416 1.1 itohy default:
417 1.1 itohy printf("%s: write: unexpected response %#x, %#x, sz %d\n",
418 1.1 itohy sc->sc_pt[sc->sc_reqw.pt].pt_name,
419 1.1 itohy ntohl(response->response_code),
420 1.1 itohy ntohl(rm->func_code), sz);
421 1.1 itohy mlcdstart_bp(sc, bp); /* retry */
422 1.1 itohy break;
423 1.1 itohy }
424 1.1 itohy break;
425 1.1 itohy
426 1.1 itohy default:
427 1.1 itohy break;
428 1.1 itohy }
429 1.1 itohy }
430 1.1 itohy
431 1.1 itohy static void
432 1.1 itohy mlcd_printerror(head, code)
433 1.1 itohy const char *head;
434 1.1 itohy u_int32_t code;
435 1.1 itohy {
436 1.1 itohy
437 1.1 itohy printf("%s:", head);
438 1.1 itohy NTOHL(code);
439 1.1 itohy if (code & 1)
440 1.1 itohy printf(" PT error");
441 1.1 itohy if (code & 2)
442 1.1 itohy printf(" Phase error");
443 1.1 itohy if (code & 4)
444 1.1 itohy printf(" Block error");
445 1.1 itohy if (code & 010)
446 1.1 itohy printf(" Write error");
447 1.1 itohy if (code & 020)
448 1.1 itohy printf(" Length error");
449 1.1 itohy if (code & ~037)
450 1.1 itohy printf(" Unknown error %#x", code & ~037);
451 1.1 itohy printf("\n");
452 1.1 itohy }
453 1.1 itohy
454 1.1 itohy int
455 1.1 itohy mlcdopen(dev, flags, devtype, p)
456 1.1 itohy dev_t dev;
457 1.1 itohy int flags, devtype;
458 1.1 itohy struct proc *p;
459 1.1 itohy {
460 1.1 itohy int unit, part;
461 1.1 itohy struct mlcd_softc *sc;
462 1.1 itohy struct mlcd_pt *pt;
463 1.1 itohy
464 1.1 itohy unit = MLCD_UNIT(dev);
465 1.1 itohy part = MLCD_PART(dev);
466 1.1 itohy if ((sc = device_lookup(&mlcd_cd, unit)) == NULL
467 1.1 itohy || sc->sc_stat == MLCD_INIT
468 1.1 itohy || sc->sc_stat == MLCD_INIT2
469 1.1 itohy || part >= sc->sc_npt || (pt = &sc->sc_pt[part])->pt_flags == 0)
470 1.1 itohy return ENXIO;
471 1.1 itohy
472 1.1 itohy if (pt->pt_flags & MLCD_PT_OPEN)
473 1.1 itohy return EBUSY;
474 1.1 itohy
475 1.1 itohy pt->pt_flags |= MLCD_PT_OPEN;
476 1.1 itohy
477 1.1 itohy return 0;
478 1.1 itohy }
479 1.1 itohy
480 1.1 itohy int
481 1.1 itohy mlcdclose(dev, flags, devtype, p)
482 1.1 itohy dev_t dev;
483 1.1 itohy int flags, devtype;
484 1.1 itohy struct proc *p;
485 1.1 itohy {
486 1.1 itohy int unit, part;
487 1.1 itohy struct mlcd_softc *sc;
488 1.1 itohy struct mlcd_pt *pt;
489 1.1 itohy
490 1.1 itohy unit = MLCD_UNIT(dev);
491 1.1 itohy part = MLCD_PART(dev);
492 1.1 itohy sc = mlcd_cd.cd_devs[unit];
493 1.1 itohy pt = &sc->sc_pt[part];
494 1.1 itohy
495 1.1 itohy pt->pt_flags &= ~MLCD_PT_OPEN;
496 1.1 itohy
497 1.1 itohy return 0;
498 1.1 itohy }
499 1.1 itohy
500 1.1 itohy void
501 1.1 itohy mlcdstrategy(bp)
502 1.1 itohy struct buf *bp;
503 1.1 itohy {
504 1.1 itohy int dev, unit, part;
505 1.1 itohy struct mlcd_softc *sc;
506 1.1 itohy struct mlcd_pt *pt;
507 1.1 itohy daddr_t off, nblk, cnt;
508 1.1 itohy
509 1.1 itohy dev = bp->b_dev;
510 1.1 itohy unit = MLCD_UNIT(dev);
511 1.1 itohy part = MLCD_PART(dev);
512 1.1 itohy sc = mlcd_cd.cd_devs[unit];
513 1.1 itohy pt = &sc->sc_pt[part];
514 1.1 itohy
515 1.1 itohy #if 0
516 1.1 itohy printf("%s: mlcdstrategy: blkno %d, count %ld\n",
517 1.1 itohy pt->pt_name, bp->b_blkno, bp->b_bcount);
518 1.1 itohy #endif
519 1.1 itohy
520 1.1 itohy if (bp->b_flags & B_READ)
521 1.1 itohy goto inval; /* no read */
522 1.1 itohy
523 1.1 itohy cnt = howmany(bp->b_bcount, sc->sc_bsize);
524 1.1 itohy if (cnt == 0)
525 1.1 itohy goto done; /* no work */
526 1.1 itohy
527 1.1 itohy /* XXX We have set the transfer is only one block in mlcd_minphys(). */
528 1.1 itohy KASSERT(cnt == 1);
529 1.1 itohy
530 1.1 itohy if (bp->b_blkno & ~(~(daddr_t)0 >> (DEV_BSHIFT + 1 /* sign bit */))
531 1.1 itohy /*|| (bp->b_bcount % sc->sc_bsize) != 0*/)
532 1.1 itohy goto inval;
533 1.1 itohy
534 1.1 itohy off = bp->b_blkno * DEV_BSIZE / sc->sc_bsize;
535 1.1 itohy nblk = pt->pt_nblk;
536 1.1 itohy
537 1.1 itohy /* deal with the EOF condition */
538 1.1 itohy if (off + cnt > nblk) {
539 1.1 itohy if (off >= nblk) {
540 1.1 itohy if (off == nblk) {
541 1.1 itohy bp->b_resid = bp->b_bcount;
542 1.1 itohy goto done;
543 1.1 itohy }
544 1.1 itohy goto inval;
545 1.1 itohy }
546 1.1 itohy cnt = nblk - off;
547 1.1 itohy bp->b_resid = bp->b_bcount - (cnt * sc->sc_bsize);
548 1.1 itohy }
549 1.1 itohy
550 1.1 itohy bp->b_rawblkno = off;
551 1.1 itohy
552 1.1 itohy /* queue this transfer */
553 1.1 itohy BUFQ_PUT(&sc->sc_q, bp);
554 1.1 itohy
555 1.1 itohy if (sc->sc_stat == MLCD_IDLE)
556 1.1 itohy mlcdstart(sc);
557 1.1 itohy
558 1.1 itohy return;
559 1.1 itohy
560 1.1 itohy inval: bp->b_error = EINVAL;
561 1.1 itohy bp->b_flags |= B_ERROR;
562 1.1 itohy done: biodone(bp);
563 1.1 itohy }
564 1.1 itohy
565 1.1 itohy /*
566 1.1 itohy * start I/O operations
567 1.1 itohy */
568 1.1 itohy static void
569 1.1 itohy mlcdstart(sc)
570 1.1 itohy struct mlcd_softc *sc;
571 1.1 itohy {
572 1.1 itohy struct buf *bp;
573 1.1 itohy
574 1.1 itohy if ((bp = BUFQ_GET(&sc->sc_q)) == NULL) {
575 1.1 itohy sc->sc_stat = MLCD_IDLE;
576 1.1 itohy maple_enable_unit_ping(sc->sc_parent, sc->sc_unit,
577 1.1 itohy MAPLE_FN_LCD, 1);
578 1.1 itohy return;
579 1.1 itohy }
580 1.1 itohy
581 1.1 itohy sc->sc_retry = 0;
582 1.1 itohy mlcdstart_bp(sc, bp);
583 1.1 itohy }
584 1.1 itohy
585 1.1 itohy /*
586 1.1 itohy * start/retry a specified I/O operation
587 1.1 itohy */
588 1.1 itohy static void
589 1.1 itohy mlcdstart_bp(sc, bp)
590 1.1 itohy struct mlcd_softc *sc;
591 1.1 itohy struct buf *bp;
592 1.1 itohy {
593 1.1 itohy int part;
594 1.1 itohy struct mlcd_pt *pt;
595 1.1 itohy
596 1.1 itohy part = MLCD_PART(bp->b_dev);
597 1.1 itohy pt = &sc->sc_pt[part];
598 1.1 itohy
599 1.1 itohy /* handle retry */
600 1.1 itohy if (sc->sc_retry++ > MLCD_MAXRETRY) {
601 1.1 itohy /* retry count exceeded */
602 1.1 itohy bp->b_error = EIO;
603 1.1 itohy bp->b_flags |= B_ERROR;
604 1.1 itohy mlcddone(sc);
605 1.1 itohy return;
606 1.1 itohy }
607 1.1 itohy
608 1.1 itohy sc->sc_bp = bp;
609 1.1 itohy /* sc->sc_cnt = cnt; */ /* cnt is always 1 */
610 1.1 itohy
611 1.1 itohy /*
612 1.1 itohy * I/O access will fail if the removal detection (by maple driver)
613 1.1 itohy * occurs before finishing the I/O, so disable it.
614 1.1 itohy * We are sending commands, and the removal detection is still alive.
615 1.1 itohy */
616 1.1 itohy maple_enable_unit_ping(sc->sc_parent, sc->sc_unit, MAPLE_FN_LCD, 0);
617 1.1 itohy
618 1.1 itohy /*
619 1.1 itohy * Start the first phase (phase# = 0).
620 1.1 itohy */
621 1.1 itohy KASSERT((bp->b_flags & B_READ) == 0);
622 1.1 itohy /* write */
623 1.1 itohy sc->sc_stat = MLCD_WRITE;
624 1.1 itohy sc->sc_reqw.func_code = htonl(MAPLE_FUNC(MAPLE_FN_LCD));
625 1.1 itohy sc->sc_reqw.pt = part;
626 1.1 itohy sc->sc_reqw.block = htons(bp->b_rawblkno);
627 1.1 itohy sc->sc_reqw.phase = 0; /* first phase */
628 1.1 itohy bcopy(bp->b_data /* + sc->sc_waccsz * phase */,
629 1.1 itohy sc->sc_reqw.data, sc->sc_waccsz);
630 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, MAPLE_FN_LCD,
631 1.1 itohy MAPLE_COMMAND_BWRITE, MLCD_SIZE_REQW(sc) / 4, &sc->sc_reqw, 0);
632 1.1 itohy }
633 1.1 itohy
634 1.1 itohy static void
635 1.1 itohy mlcddone(sc)
636 1.1 itohy struct mlcd_softc *sc;
637 1.1 itohy {
638 1.1 itohy struct buf *bp;
639 1.1 itohy
640 1.1 itohy /* terminate current transfer */
641 1.1 itohy bp = sc->sc_bp;
642 1.1 itohy KASSERT(bp);
643 1.1 itohy sc->sc_bp = NULL;
644 1.1 itohy biodone(bp);
645 1.1 itohy
646 1.1 itohy /* go next transfer */
647 1.1 itohy mlcdstart(sc);
648 1.1 itohy }
649 1.1 itohy
650 1.1 itohy static void mlcd_minphys __P((struct buf *));
651 1.1 itohy
652 1.1 itohy static void
653 1.1 itohy mlcd_minphys(bp)
654 1.1 itohy struct buf *bp;
655 1.1 itohy {
656 1.1 itohy int unit;
657 1.1 itohy struct mlcd_softc *sc;
658 1.1 itohy
659 1.1 itohy unit = MLCD_UNIT(bp->b_dev);
660 1.1 itohy sc = mlcd_cd.cd_devs[unit];
661 1.1 itohy
662 1.1 itohy /* XXX one block only */
663 1.1 itohy if (bp->b_bcount > sc->sc_bsize)
664 1.1 itohy bp->b_bcount = sc->sc_bsize;
665 1.1 itohy }
666 1.1 itohy
667 1.1 itohy int
668 1.1 itohy mlcdwrite(dev, uio, flags)
669 1.1 itohy dev_t dev;
670 1.1 itohy struct uio *uio;
671 1.1 itohy int flags;
672 1.1 itohy {
673 1.1 itohy
674 1.1 itohy return (physio(mlcdstrategy, NULL, dev, B_WRITE, mlcd_minphys, uio));
675 1.1 itohy }
676 1.1 itohy
677 1.1 itohy int
678 1.1 itohy mlcdioctl(dev, cmd, data, flag, p)
679 1.1 itohy dev_t dev;
680 1.1 itohy u_long cmd;
681 1.1 itohy caddr_t data;
682 1.1 itohy int flag;
683 1.1 itohy struct proc *p;
684 1.1 itohy {
685 1.1 itohy int unit, part;
686 1.1 itohy struct mlcd_softc *sc;
687 1.1 itohy struct mlcd_pt *pt;
688 1.1 itohy
689 1.1 itohy unit = MLCD_UNIT(dev);
690 1.1 itohy part = MLCD_PART(dev);
691 1.1 itohy sc = mlcd_cd.cd_devs[unit];
692 1.1 itohy pt = &sc->sc_pt[part];
693 1.1 itohy
694 1.1 itohy switch (cmd) {
695 1.1 itohy
696 1.1 itohy default:
697 1.1 itohy /* generic maple ioctl */
698 1.1 itohy return maple_unit_ioctl(sc->sc_parent, sc->sc_unit, cmd, data,
699 1.1 itohy flag, p);
700 1.1 itohy }
701 1.1 itohy
702 1.1 itohy return 0;
703 1.1 itohy }
704