flash_ebus.c revision 1.3 1 1.3 tls /* $NetBSD: flash_ebus.c,v 1.3 2011/11/19 22:51:19 tls Exp $ */
2 1.1 pooka
3 1.1 pooka /*-
4 1.1 pooka * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 1.1 pooka * All rights reserved.
6 1.1 pooka *
7 1.1 pooka * This code was written by Alessandro Forin and Neil Pittman
8 1.1 pooka * at Microsoft Research and contributed to The NetBSD Foundation
9 1.1 pooka * by Microsoft Corporation.
10 1.1 pooka *
11 1.1 pooka * Redistribution and use in source and binary forms, with or without
12 1.1 pooka * modification, are permitted provided that the following conditions
13 1.1 pooka * are met:
14 1.1 pooka * 1. Redistributions of source code must retain the above copyright
15 1.1 pooka * notice, this list of conditions and the following disclaimer.
16 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 pooka * notice, this list of conditions and the following disclaimer in the
18 1.1 pooka * documentation and/or other materials provided with the distribution.
19 1.1 pooka *
20 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 1.1 pooka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.1 pooka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.1 pooka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.1 pooka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.1 pooka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.1 pooka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.1 pooka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.1 pooka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.1 pooka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.1 pooka * POSSIBILITY OF SUCH DAMAGE.
31 1.1 pooka */
32 1.1 pooka
33 1.1 pooka #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34 1.3 tls __KERNEL_RCSID(0, "$NetBSD: flash_ebus.c,v 1.3 2011/11/19 22:51:19 tls Exp $");
35 1.1 pooka
36 1.1 pooka /* Driver for the Intel 28F320/640/128 (J3A150) StrataFlash memory device
37 1.1 pooka * Extended to include the Intel JS28F256P30T95.
38 1.1 pooka */
39 1.1 pooka
40 1.1 pooka #include <sys/param.h>
41 1.1 pooka #include <sys/systm.h>
42 1.1 pooka #include <sys/kernel.h>
43 1.1 pooka #include <sys/proc.h>
44 1.1 pooka #include <sys/errno.h>
45 1.1 pooka #include <sys/ioctl.h>
46 1.1 pooka #include <sys/device.h>
47 1.1 pooka #include <sys/conf.h>
48 1.1 pooka #include <sys/file.h>
49 1.1 pooka #include <sys/stat.h>
50 1.1 pooka #include <sys/ioctl.h>
51 1.1 pooka #include <sys/buf.h>
52 1.1 pooka #include <sys/bufq.h>
53 1.1 pooka #include <sys/uio.h>
54 1.1 pooka #include <sys/malloc.h>
55 1.1 pooka #include <uvm/uvm_extern.h>
56 1.1 pooka #include <sys/disklabel.h>
57 1.1 pooka #include <sys/disk.h>
58 1.1 pooka #include <sys/syslog.h>
59 1.1 pooka #include <sys/vnode.h>
60 1.1 pooka #include <sys/kthread.h>
61 1.1 pooka #include <sys/lock.h>
62 1.1 pooka #include <sys/queue.h>
63 1.1 pooka
64 1.1 pooka #if NRND > 0
65 1.1 pooka #include <sys/rnd.h>
66 1.1 pooka #endif
67 1.1 pooka
68 1.1 pooka #include "locators.h"
69 1.1 pooka #include <prop/proplib.h>
70 1.1 pooka
71 1.1 pooka #include <emips/ebus/ebusvar.h>
72 1.1 pooka #include <emips/emips/machdep.h>
73 1.1 pooka #include <machine/emipsreg.h>
74 1.1 pooka
75 1.1 pooka /* Internal config switches
76 1.1 pooka */
77 1.1 pooka #define USE_BUFFERED_WRITES 0 /* Faster, but might not work in some (older) cases */
78 1.1 pooka #define Verbose 0
79 1.1 pooka
80 1.1 pooka /* Debug tools
81 1.1 pooka */
82 1.1 pooka #define DEBUG_INTR 0x01
83 1.1 pooka #define DEBUG_XFERS 0x02
84 1.1 pooka #define DEBUG_STATUS 0x04
85 1.1 pooka #define DEBUG_FUNCS 0x08
86 1.1 pooka #define DEBUG_PROBE 0x10
87 1.1 pooka #define DEBUG_WRITES 0x20
88 1.1 pooka #define DEBUG_READS 0x40
89 1.1 pooka #define DEBUG_ERRORS 0x80
90 1.1 pooka #ifdef DEBUG
91 1.1 pooka int eflash_debug = DEBUG_ERRORS;
92 1.1 pooka #define EFLASH_DEBUG(x) (eflash_debug & (x))
93 1.1 pooka #define DBGME(_lev_,_x_) if ((_lev_) & eflash_debug) _x_
94 1.1 pooka #else
95 1.1 pooka #define EFLASH_DEBUG(x) (0)
96 1.1 pooka #define DBGME(_lev_,_x_)
97 1.1 pooka #endif
98 1.1 pooka #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_)
99 1.1 pooka
100 1.1 pooka /* Product ID codes
101 1.1 pooka */
102 1.1 pooka #define MANUF_INTEL 0x89
103 1.1 pooka #define DEVICE_320 0x16
104 1.1 pooka #define DEVICE_640 0x17
105 1.1 pooka #define DEVICE_128 0x18
106 1.1 pooka #define DEVICE_256 0x19
107 1.1 pooka
108 1.1 pooka /* Table of chips we understand.
109 1.1 pooka */
110 1.1 pooka #define nDELTAS 3
111 1.1 pooka struct flash_type {
112 1.1 pooka struct {
113 1.1 pooka uint32_t nSectors;
114 1.1 pooka uint32_t nKB;
115 1.1 pooka } ft_deltas[nDELTAS];
116 1.1 pooka uint8_t ft_manuf_code;
117 1.1 pooka uint8_t ft_device_code;
118 1.1 pooka uint16_t ft_total_sectors;
119 1.1 pooka const char *ft_name;
120 1.1 pooka };
121 1.1 pooka
122 1.1 pooka static const struct flash_type sector_maps[] = {
123 1.1 pooka {
124 1.1 pooka {{32,128},{0,0},},
125 1.1 pooka MANUF_INTEL, DEVICE_320, 32, /* a J3 part */
126 1.1 pooka "StrataFlash 28F320"
127 1.1 pooka },
128 1.1 pooka {
129 1.1 pooka {{64,128},{0,0},},
130 1.1 pooka MANUF_INTEL, DEVICE_640, 64, /* a J3 part */
131 1.1 pooka "StrataFlash 28F640"
132 1.1 pooka },
133 1.1 pooka {
134 1.1 pooka {{128,128},{0,0},},
135 1.1 pooka MANUF_INTEL, DEVICE_128, 128, /* a J3 part */
136 1.1 pooka "StrataFlash 28F128"
137 1.1 pooka },
138 1.1 pooka {
139 1.1 pooka {{255,128},{4,32},{0,0}},
140 1.1 pooka MANUF_INTEL, DEVICE_256, 259, /* a P30 part */
141 1.1 pooka "StrataFlash 28F256"
142 1.1 pooka }
143 1.1 pooka };
144 1.1 pooka #define nMAPS ((sizeof sector_maps) / (sizeof sector_maps[0]))
145 1.1 pooka
146 1.1 pooka /* Instead of dragging in atavar.h.. */
147 1.1 pooka struct eflash_bio {
148 1.1 pooka volatile int flags;/* cmd flags */
149 1.1 pooka #define ATA_POLL 0x0002 /* poll for completion */
150 1.1 pooka #define ATA_SINGLE 0x0008 /* transfer must be done in singlesector mode */
151 1.1 pooka #define ATA_READ 0x0020 /* transfer is a read (otherwise a write) */
152 1.1 pooka #define ATA_CORR 0x0040 /* transfer had a corrected error */
153 1.1 pooka daddr_t blkno; /* block addr */
154 1.1 pooka daddr_t blkdone;/* number of blks transferred */
155 1.1 pooka size_t nblks; /* number of blocks currently transferring */
156 1.1 pooka size_t nbytes; /* number of bytes currently transferring */
157 1.1 pooka char *databuf;/* data buffer address */
158 1.1 pooka volatile int error;
159 1.1 pooka u_int32_t r_error;/* copy of status register */
160 1.1 pooka #ifdef HAS_BAD144_HANDLING
161 1.1 pooka daddr_t badsect[127];/* 126 plus trailing -1 marker */
162 1.1 pooka #endif
163 1.1 pooka };
164 1.1 pooka /* End of atavar.h*/
165 1.1 pooka
166 1.1 pooka /* chip-specific functions
167 1.1 pooka */
168 1.1 pooka struct flash_ops;
169 1.1 pooka
170 1.1 pooka /*
171 1.1 pooka * Device softc
172 1.1 pooka */
173 1.1 pooka struct eflash_softc {
174 1.1 pooka device_t sc_dev;
175 1.1 pooka
176 1.1 pooka /* General disk infos */
177 1.1 pooka struct disk sc_dk;
178 1.1 pooka struct bufq_state *sc_q;
179 1.1 pooka struct callout sc_restart_ch;
180 1.1 pooka
181 1.1 pooka /* IDE disk soft states */
182 1.1 pooka struct buf *sc_bp; /* buf being transfered */
183 1.1 pooka struct buf *active_xfer; /* buf handoff to thread */
184 1.1 pooka struct eflash_bio sc_bio; /* current transfer */
185 1.1 pooka
186 1.1 pooka struct proc *ch_thread;
187 1.1 pooka int ch_flags;
188 1.1 pooka #define ATACH_SHUTDOWN 0x02 /* thread is shutting down */
189 1.1 pooka #define ATACH_IRQ_WAIT 0x10 /* thread is waiting for irq */
190 1.1 pooka #define ATACH_DISABLED 0x80 /* channel is disabled */
191 1.1 pooka #define ATACH_TH_RUN 0x100 /* the kernel thread is working */
192 1.1 pooka #define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */
193 1.1 pooka
194 1.1 pooka int openings;
195 1.1 pooka int sc_flags;
196 1.1 pooka #define EFLASHF_WLABEL 0x004 /* label is writable */
197 1.1 pooka #define EFLASHF_LABELLING 0x008 /* writing label */
198 1.1 pooka #define EFLASHF_LOADED 0x010 /* parameters loaded */
199 1.1 pooka #define EFLASHF_WAIT 0x020 /* waiting for resources */
200 1.1 pooka #define EFLASHF_KLABEL 0x080 /* retain label after 'full' close */
201 1.1 pooka
202 1.1 pooka int retries; /* number of xfer retry */
203 1.1 pooka
204 1.1 pooka #if NRND > 0
205 1.3 tls krndsource_t rnd_source;
206 1.1 pooka #endif
207 1.1 pooka
208 1.1 pooka /* flash-specific state */
209 1.1 pooka struct _Flash *sc_dp;
210 1.1 pooka uint32_t sc_size;
211 1.1 pooka uint32_t sc_capacity;
212 1.1 pooka paddr_t sc_base;
213 1.1 pooka volatile uint8_t *sc_page0;
214 1.1 pooka
215 1.1 pooka /* current read-write sector mapping */
216 1.1 pooka /*volatile*/ uint8_t *sc_sector;
217 1.1 pooka uint32_t sc_sector_size;
218 1.1 pooka uint32_t sc_sector_offset;
219 1.1 pooka #define NOSECTOR ((uint32_t)(~0))
220 1.1 pooka int sc_erased;
221 1.1 pooka
222 1.1 pooka /* device-specificity */
223 1.1 pooka uint32_t sc_buffersize;
224 1.1 pooka vsize_t sc_max_secsize;
225 1.1 pooka unsigned int sc_chips;
226 1.1 pooka const struct flash_ops *sc_ops;
227 1.1 pooka struct flash_type sc_type;
228 1.1 pooka };
229 1.1 pooka
230 1.1 pooka static int eflash_ebus_match (struct device *, struct cfdata *, void *);
231 1.1 pooka static void eflash_ebus_attach (struct device *, struct device *, void *);
232 1.1 pooka
233 1.1 pooka CFATTACH_DECL_NEW(flash_ebus, sizeof (struct eflash_softc),
234 1.1 pooka eflash_ebus_match, eflash_ebus_attach, NULL, NULL);
235 1.1 pooka
236 1.1 pooka /* implementation decls */
237 1.1 pooka static int flash_identify(struct eflash_softc*);
238 1.1 pooka static int KBinSector(struct flash_type * SecMap, unsigned int SecNo);
239 1.1 pooka static uint32_t SectorStart(struct flash_type * SecMap, int SecNo);
240 1.1 pooka static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset);
241 1.1 pooka static void eflash_thread(void *arg);
242 1.1 pooka static int eflash_read_at (struct eflash_softc *sc, daddr_t start_sector, char *buffer,
243 1.1 pooka size_t nblocks, size_t * pSizeRead);
244 1.1 pooka static int eflash_write_at(struct eflash_softc *sc, daddr_t start_sector, char *buffer,
245 1.1 pooka size_t nblocks, size_t * pSizeWritten);
246 1.1 pooka
247 1.1 pooka /* Config functions
248 1.1 pooka */
249 1.1 pooka static int
250 1.1 pooka eflash_ebus_match(struct device *parent, struct cfdata *match, void *aux)
251 1.1 pooka {
252 1.1 pooka struct ebus_attach_args *ia = aux;
253 1.1 pooka struct _Flash *f = (struct _Flash *)ia->ia_vaddr;
254 1.1 pooka
255 1.1 pooka if (strcmp("flash", ia->ia_name) != 0)
256 1.1 pooka return (0);
257 1.1 pooka if ((f == NULL) ||
258 1.1 pooka ((f->BaseAddressAndTag & FLASHBT_TAG) != PMTTAG_FLASH))
259 1.1 pooka return (0);
260 1.1 pooka
261 1.1 pooka return (1);
262 1.1 pooka }
263 1.1 pooka
264 1.1 pooka static void
265 1.1 pooka eflash_ebus_attach(struct device *parent, struct device *self, void *aux)
266 1.1 pooka {
267 1.1 pooka struct ebus_attach_args *ia =aux;
268 1.1 pooka struct eflash_softc *sc = device_private(self);
269 1.1 pooka uint32_t base, ctrl;
270 1.1 pooka int error;
271 1.1 pooka
272 1.1 pooka /* Plan.
273 1.1 pooka * - mips_map_physmem() (with uncached) first page
274 1.1 pooka * - keep it around since we need status ops
275 1.1 pooka * - find what type it is.
276 1.1 pooka * - then mips_map_physmem() each sector as needed.
277 1.1 pooka */
278 1.1 pooka
279 1.1 pooka sc->sc_dev = self;
280 1.1 pooka sc->sc_dp = (struct _Flash*)ia->ia_vaddr;
281 1.1 pooka base = sc->sc_dp->BaseAddressAndTag & FLASHBT_BASE;
282 1.1 pooka ctrl = sc->sc_dp->Control;
283 1.1 pooka
284 1.1 pooka sc->sc_size = ctrl & FLASHST_SIZE;
285 1.1 pooka sc->sc_capacity = sc->sc_size / DEV_BSIZE;
286 1.1 pooka sc->sc_base = base;
287 1.1 pooka /* The chip is 16bit, so if we get 32bit there are two */
288 1.1 pooka sc->sc_chips = (ctrl & FLASHST_BUS_32) ? 2 : 1;
289 1.1 pooka
290 1.1 pooka /* Map the first page to see what chip we got */
291 1.1 pooka sc->sc_page0 = (volatile uint8_t *) mips_map_physmem(base, PAGE_SIZE);
292 1.1 pooka
293 1.1 pooka if (flash_identify(sc)) {
294 1.1 pooka printf(" base %x: %dMB flash memory (%d x %s)\n", base, sc->sc_size >> 20,
295 1.1 pooka sc->sc_chips, sc->sc_type.ft_name);
296 1.1 pooka } else {
297 1.1 pooka /* BUGBUG If we dont identify it stop the driver! */
298 1.1 pooka printf(": unknown manufacturer id %x, device id %x\n",
299 1.1 pooka sc->sc_type.ft_manuf_code, sc->sc_type.ft_device_code);
300 1.1 pooka }
301 1.1 pooka
302 1.1 pooka config_pending_incr();
303 1.1 pooka
304 1.1 pooka error = kthread_create(PRI_NONE, 0, NULL,
305 1.1 pooka eflash_thread, sc, NULL, "%s", device_xname(sc->sc_dev));
306 1.1 pooka if (error)
307 1.1 pooka aprint_error_dev(sc->sc_dev,
308 1.1 pooka "unable to create kernel thread: error %d\n", error);
309 1.1 pooka }
310 1.1 pooka
311 1.1 pooka /* Implementation functions
312 1.1 pooka */
313 1.1 pooka /* Returns the size in KBytes of a given sector,
314 1.1 pooka * or -1 for bad arguments.
315 1.1 pooka */
316 1.1 pooka static int KBinSector(struct flash_type * SecMap, unsigned int SecNo)
317 1.1 pooka {
318 1.1 pooka int i;
319 1.1 pooka
320 1.1 pooka for (i = 0; i < nDELTAS; i++) {
321 1.1 pooka if (SecNo < SecMap->ft_deltas[i].nSectors)
322 1.1 pooka return SecMap->ft_deltas[i].nKB;
323 1.1 pooka SecNo -= SecMap->ft_deltas[i].nSectors;
324 1.1 pooka }
325 1.1 pooka
326 1.1 pooka return -1;
327 1.1 pooka }
328 1.1 pooka
329 1.1 pooka #define SectorSize(_map_,_sector_) (1024 * KBinSector(_map_,_sector_))
330 1.1 pooka
331 1.1 pooka /* Whats the starting offset of sector N
332 1.1 pooka */
333 1.1 pooka static uint32_t SectorStart(struct flash_type * SecMap, int SecNo)
334 1.1 pooka {
335 1.1 pooka int i;
336 1.1 pooka uint32_t Offset = 0;
337 1.1 pooka
338 1.1 pooka for (i = 0; i < nDELTAS; i++) {
339 1.1 pooka if ((unsigned int)SecNo < SecMap->ft_deltas[i].nSectors)
340 1.1 pooka return 1024 * (Offset + (SecMap->ft_deltas[i].nKB * SecNo));
341 1.1 pooka SecNo -= SecMap->ft_deltas[i].nSectors;
342 1.1 pooka Offset += SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB;
343 1.1 pooka }
344 1.1 pooka
345 1.1 pooka return ~0;
346 1.1 pooka }
347 1.1 pooka
348 1.1 pooka /* What sector number corresponds to a given offset
349 1.1 pooka */
350 1.1 pooka static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset)
351 1.1 pooka {
352 1.1 pooka unsigned int i;
353 1.1 pooka unsigned int SecNo = 0;
354 1.1 pooka
355 1.1 pooka Offset /= 1024;
356 1.1 pooka for (i = 0; i < nDELTAS; i++) {
357 1.1 pooka if (Offset < (unsigned int)
358 1.1 pooka ((SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB)))
359 1.1 pooka return SecNo + (Offset / SecMap->ft_deltas[i].nKB);
360 1.1 pooka SecNo += SecMap->ft_deltas[i].nSectors;
361 1.1 pooka Offset -= SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB;
362 1.1 pooka }
363 1.1 pooka
364 1.1 pooka return ~0;
365 1.1 pooka }
366 1.1 pooka
367 1.1 pooka /*
368 1.1 pooka * Semi-generic operations
369 1.1 pooka */
370 1.1 pooka struct flash_ops {
371 1.1 pooka void (*write_uint8) (struct eflash_softc *sc, volatile void *Offset, uint8_t Value);
372 1.1 pooka void (*read_uint8) (struct eflash_softc *sc, volatile void *Offset, uint8_t *Value);
373 1.1 pooka void (*write_uint16) (struct eflash_softc *sc, volatile void *Offset, uint16_t Value);
374 1.1 pooka void (*read_uint16) (struct eflash_softc *sc, volatile void *Offset, uint16_t *Value);
375 1.1 pooka void (*write_uint32) (struct eflash_softc *sc, volatile void *Offset, uint32_t Value);
376 1.1 pooka void (*read_uint32) (struct eflash_softc *sc, volatile void *Offset, uint32_t *Value);
377 1.1 pooka int (*program_word) (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues,
378 1.1 pooka int Verify, int *nWritten);
379 1.1 pooka int (*program_buffer) (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues,
380 1.1 pooka int Verify, int *nWritten);
381 1.1 pooka };
382 1.1 pooka
383 1.1 pooka /*
384 1.1 pooka * Hardware access proper, single-chip
385 1.1 pooka */
386 1.1 pooka static void single_write_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t Value)
387 1.1 pooka {
388 1.1 pooka volatile uint8_t * Where = Offset;
389 1.1 pooka *Where = Value;
390 1.1 pooka }
391 1.1 pooka
392 1.1 pooka static void single_read_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value)
393 1.1 pooka {
394 1.1 pooka volatile uint8_t * Where = Offset;
395 1.1 pooka *Value = *Where;
396 1.1 pooka }
397 1.1 pooka
398 1.1 pooka static void single_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value)
399 1.1 pooka {
400 1.1 pooka volatile uint16_t * Where = Offset;
401 1.1 pooka *Where = Value;
402 1.1 pooka }
403 1.1 pooka
404 1.1 pooka static void single_read_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value)
405 1.1 pooka {
406 1.1 pooka volatile uint16_t * Where = Offset;
407 1.1 pooka *Value = *Where;
408 1.1 pooka }
409 1.1 pooka
410 1.1 pooka /* This one should not be used, probably */
411 1.1 pooka static void single_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value)
412 1.1 pooka {
413 1.1 pooka #if 0
414 1.1 pooka /* The chip cannot take back-to-back writes */
415 1.1 pooka volatile uint32_t * Where = Offset;
416 1.1 pooka *Where = Value;
417 1.1 pooka #else
418 1.1 pooka volatile uint8_t * Where = Offset;
419 1.1 pooka uint16_t v0, v1;
420 1.1 pooka
421 1.1 pooka /* Unfortunately, this is bytesex dependent */
422 1.1 pooka #if (BYTE_ORDER == BIG_ENDIAN)
423 1.1 pooka v1 = (uint16_t) Value;
424 1.1 pooka v0 = (uint16_t) (Value >> 16);
425 1.1 pooka #else
426 1.1 pooka v0 = (uint16_t) Value;
427 1.1 pooka v1 = (uint16_t) (Value >> 16);
428 1.1 pooka #endif
429 1.1 pooka single_write_uint16(sc,Where,v0);
430 1.1 pooka single_write_uint16(sc,Where+2,v1);
431 1.1 pooka #endif
432 1.1 pooka }
433 1.1 pooka
434 1.1 pooka static void single_read_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value)
435 1.1 pooka {
436 1.1 pooka /* back-to-back reads must be ok */
437 1.1 pooka volatile uint32_t * Where = Offset;
438 1.1 pooka *Value = *Where;
439 1.1 pooka }
440 1.1 pooka
441 1.1 pooka /*
442 1.1 pooka * Hardware access proper, paired-chips
443 1.1 pooka * NB: This set of ops assumes two chips in parallel on a 32bit bus,
444 1.1 pooka * each operation is repeated in parallel to both chips
445 1.1 pooka */
446 1.1 pooka static void twin_write_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t Value)
447 1.1 pooka {
448 1.1 pooka volatile uint32_t * Where = Offset;
449 1.1 pooka uint32_t v = Value | ((uint32_t)Value << 16);
450 1.1 pooka
451 1.1 pooka v = le32toh(v);
452 1.1 pooka *Where = v;
453 1.1 pooka }
454 1.1 pooka
455 1.1 pooka static void twin_read_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value)
456 1.1 pooka {
457 1.1 pooka volatile uint32_t * Where = Offset;
458 1.1 pooka uint32_t v;
459 1.1 pooka v = *Where;
460 1.1 pooka v = le32toh(v);
461 1.1 pooka *Value = (uint8_t) v;
462 1.1 pooka }
463 1.1 pooka
464 1.1 pooka /* This one should *not* be used, error-prone */
465 1.1 pooka static void twin_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value)
466 1.1 pooka {
467 1.1 pooka volatile uint16_t * Where = Offset;
468 1.1 pooka *Where = Value;
469 1.1 pooka }
470 1.1 pooka
471 1.1 pooka static void twin_read_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value)
472 1.1 pooka {
473 1.1 pooka volatile uint16_t * Where = Offset;
474 1.1 pooka *Value = *Where;
475 1.1 pooka }
476 1.1 pooka
477 1.1 pooka static void twin_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value)
478 1.1 pooka {
479 1.1 pooka volatile uint32_t * Where = Offset;
480 1.1 pooka Value = le32toh(Value);
481 1.1 pooka *Where = Value;
482 1.1 pooka }
483 1.1 pooka
484 1.1 pooka static void twin_read_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value)
485 1.1 pooka {
486 1.1 pooka volatile uint32_t * Where = Offset;
487 1.1 pooka uint32_t v;
488 1.1 pooka v = *Where;
489 1.1 pooka v = le32toh(v);
490 1.1 pooka *Value = v;
491 1.1 pooka }
492 1.1 pooka
493 1.1 pooka /*
494 1.1 pooka * Command and status definitions
495 1.1 pooka */
496 1.1 pooka
497 1.1 pooka /* Defines for the STATUS register
498 1.1 pooka */
499 1.1 pooka #define ST_reserved 0x01
500 1.1 pooka #define ST_BLOCK_LOCKED 0x02
501 1.1 pooka #define ST_PROGRAM_SUSPENDED 0x04
502 1.1 pooka #define ST_LOW_VOLTAGE 0x08
503 1.1 pooka #define ST_LOCK_BIT_ERROR 0x10
504 1.1 pooka #define ST_ERASE_ERROR 0x20
505 1.1 pooka #define ST_ERASE_SUSPENDED 0x40
506 1.1 pooka #define ST_READY 0x80
507 1.1 pooka #define ST_ERASE_MASK 0xee /* bits to check after erase command */
508 1.1 pooka #define ST_MASK 0xfe /* ignore reserved */
509 1.1 pooka
510 1.1 pooka /* Command set (what we use of it)
511 1.1 pooka */
512 1.1 pooka #define CMD_CONFIRM 0xd0
513 1.1 pooka #define CMD_READ_ARRAY 0xff
514 1.1 pooka #define CMD_READ_ID 0x90
515 1.1 pooka #define CMD_READ_STATUS 0x70
516 1.1 pooka #define CMD_CLEAR_STATUS 0x50
517 1.1 pooka #define CMD_WRITE_WORD 0x40
518 1.1 pooka #define CMD_WRITE_BUFFER 0xe8
519 1.1 pooka #define CMD_ERASE_SETUP 0x20
520 1.1 pooka #define CMD_ERASE_CONFIRM CMD_CONFIRM
521 1.1 pooka #define CMD_SET_PREFIX 0x60 /* set read config, lock bits */
522 1.1 pooka #define CMD_LOCK 0x01
523 1.1 pooka #define CMD_UNLOCK CMD_CONFIRM
524 1.1 pooka /* What we dont use of it
525 1.1 pooka */
526 1.1 pooka #define CMD_READ_QUERY 0x98
527 1.1 pooka # define BUFFER_BYTES 32
528 1.1 pooka #define CMD_ERASE_SUSPEND 0xb0
529 1.1 pooka #define CMD_ERASE_RESUME CMD_CONFIRM
530 1.1 pooka #define CMD_CONFIGURATION 0xb8
531 1.1 pooka #define CMD_PROTECT 0xc0
532 1.1 pooka
533 1.1 pooka /* Enter the Product ID mode (Read Identifier Codes)
534 1.1 pooka */
535 1.1 pooka static void ProductIdEnter(struct eflash_softc *sc)
536 1.1 pooka {
537 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ID);
538 1.1 pooka }
539 1.1 pooka
540 1.1 pooka /* Exit the Product ID mode (enter Read Array mode)
541 1.1 pooka */
542 1.1 pooka static void ProductIdExit(struct eflash_softc *sc)
543 1.1 pooka {
544 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY);
545 1.1 pooka }
546 1.1 pooka
547 1.1 pooka /* Read the status register
548 1.1 pooka */
549 1.1 pooka static uint8_t ReadStatusRegister(struct eflash_softc *sc)
550 1.1 pooka {
551 1.1 pooka uint8_t Status;
552 1.1 pooka
553 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_STATUS);
554 1.1 pooka sc->sc_ops->read_uint8(sc,sc->sc_page0,&Status);
555 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY);
556 1.1 pooka return Status;
557 1.1 pooka }
558 1.1 pooka
559 1.1 pooka /* Clear error bits in status
560 1.1 pooka */
561 1.1 pooka static void ClearStatusRegister(struct eflash_softc *sc)
562 1.1 pooka {
563 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_CLEAR_STATUS);
564 1.1 pooka }
565 1.1 pooka
566 1.1 pooka #if DEBUG
567 1.1 pooka /* Decode status bits
568 1.1 pooka */
569 1.1 pooka typedef const char *string;
570 1.1 pooka
571 1.1 pooka static void PrintStatus(uint8_t Status)
572 1.1 pooka {
573 1.1 pooka /* BUGBUG there's a %b format I think? */
574 1.1 pooka string BitNames[8] = {
575 1.1 pooka "reserved", "BLOCK_LOCKED",
576 1.1 pooka "PROGRAM_SUSPENDED", "LOW_VOLTAGE",
577 1.1 pooka "LOCK_BIT_ERROR", "ERASE_ERROR",
578 1.1 pooka "ERASE_SUSPENDED", "READY"
579 1.1 pooka };
580 1.1 pooka int i;
581 1.1 pooka int OneSet = FALSE;
582 1.1 pooka
583 1.1 pooka printf("[status %x =",Status);
584 1.1 pooka for (i = 0; i < 8; i++) {
585 1.1 pooka if (Status & (1<<i)) {
586 1.1 pooka printf("%c%s",
587 1.1 pooka (OneSet) ? '|' : ' ',
588 1.1 pooka BitNames[i]);
589 1.1 pooka OneSet = TRUE;
590 1.1 pooka }
591 1.1 pooka }
592 1.1 pooka printf("]\n");
593 1.1 pooka }
594 1.1 pooka #else
595 1.1 pooka #define PrintStatus(x)
596 1.1 pooka #endif
597 1.1 pooka
598 1.1 pooka /*
599 1.1 pooka * The device can lock up under certain conditions.
600 1.1 pooka * There is no software workaround [must toggle RP# to GND]
601 1.1 pooka * Check if it seems that we are in that state.
602 1.1 pooka */
603 1.1 pooka static int IsIrresponsive(struct eflash_softc *sc)
604 1.1 pooka {
605 1.1 pooka uint8_t Status = ReadStatusRegister(sc);
606 1.1 pooka
607 1.1 pooka if (Status & ST_READY)
608 1.1 pooka return FALSE;
609 1.1 pooka
610 1.1 pooka if ((Status & ST_ERASE_MASK) ==
611 1.1 pooka (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) {
612 1.1 pooka /* yes, looks that way */
613 1.1 pooka return TRUE;
614 1.1 pooka }
615 1.1 pooka
616 1.1 pooka /* Something is indeed amiss, but we dont really know for sure */
617 1.1 pooka PrintStatus(ReadStatusRegister(sc));
618 1.1 pooka ClearStatusRegister(sc);
619 1.1 pooka PrintStatus(ReadStatusRegister(sc));
620 1.1 pooka
621 1.1 pooka if ((Status & ST_MASK) ==
622 1.1 pooka (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) {
623 1.1 pooka /* yes, looks that way */
624 1.1 pooka return TRUE;
625 1.1 pooka }
626 1.1 pooka
627 1.1 pooka return FALSE;
628 1.1 pooka }
629 1.1 pooka
630 1.1 pooka
631 1.1 pooka /* Write one 16bit word
632 1.1 pooka */
633 1.1 pooka static int
634 1.1 pooka single_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
635 1.1 pooka int Verify, int *nWritten)
636 1.1 pooka {
637 1.1 pooka uint8_t Status;
638 1.1 pooka uint16_t i, Data16, Value;
639 1.1 pooka
640 1.1 pooka *nWritten = 0;
641 1.1 pooka
642 1.1 pooka Value = Values[0];
643 1.1 pooka
644 1.1 pooka if (Verify) {
645 1.1 pooka sc->sc_ops->read_uint16(sc,Offset,&Data16);
646 1.1 pooka #ifdef Verbose
647 1.1 pooka if (Verbose) {
648 1.1 pooka printf("Location %p was x%x\n",
649 1.1 pooka Offset, Data16);
650 1.1 pooka }
651 1.1 pooka #endif
652 1.1 pooka if (Data16 != 0xffff)
653 1.1 pooka printf("Offset %p not ERASED, wont take.\n",Offset);
654 1.1 pooka }
655 1.1 pooka
656 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD);
657 1.1 pooka sc->sc_ops->write_uint16(sc,Offset,Value);
658 1.1 pooka
659 1.1 pooka /* Wait until the operation is completed
660 1.1 pooka * Specs say it takes between 210 and 630 us
661 1.1 pooka * Errata says 360 TYP and Max=TBD (sic)
662 1.1 pooka */
663 1.1 pooka DELAY(800);
664 1.1 pooka
665 1.1 pooka for (i = 0; i < 10; i++) {
666 1.1 pooka sc->sc_ops->read_uint8(sc,Offset,&Status);
667 1.1 pooka if ((Status & ST_READY)) break;
668 1.1 pooka DELAY(100);
669 1.1 pooka }
670 1.1 pooka
671 1.1 pooka ProductIdExit(sc);
672 1.1 pooka
673 1.1 pooka if (Verify) {
674 1.1 pooka sc->sc_ops->read_uint16(sc,Offset,&Data16);
675 1.1 pooka #ifdef Verbose
676 1.1 pooka if (Verbose) {
677 1.1 pooka printf("Location %p is now x%x\n",
678 1.1 pooka Offset, Data16);
679 1.1 pooka }
680 1.1 pooka #endif
681 1.1 pooka if ((Data16 != Value)) {
682 1.1 pooka PrintStatus(Status);
683 1.1 pooka printf(". That didnt work, try again.. [%x != %x]\n",
684 1.1 pooka Data16, Value);
685 1.1 pooka ClearStatusRegister(sc);
686 1.1 pooka return FALSE;
687 1.1 pooka }
688 1.1 pooka }
689 1.1 pooka
690 1.1 pooka *nWritten = 2;
691 1.1 pooka return TRUE;
692 1.1 pooka }
693 1.1 pooka
694 1.1 pooka /* Write one buffer, 16bit words at a time
695 1.1 pooka */
696 1.1 pooka static int
697 1.1 pooka single_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
698 1.1 pooka int Verify, int *nWritten)
699 1.1 pooka {
700 1.1 pooka uint8_t Status;
701 1.1 pooka uint16_t i, Data16, Value = 0;
702 1.1 pooka volatile uint8_t *Where = Offset;
703 1.1 pooka
704 1.1 pooka *nWritten = 0;
705 1.1 pooka if (sc->sc_buffersize == 0)
706 1.1 pooka return FALSE; /* sanity */
707 1.1 pooka
708 1.1 pooka if (Verify) {
709 1.1 pooka for (i = 0; i < sc->sc_buffersize; i+= 2) {
710 1.1 pooka sc->sc_ops->read_uint16(sc,Where+i,&Data16);
711 1.1 pooka #ifdef Verbose
712 1.1 pooka if (Verbose) {
713 1.1 pooka printf("Location %p was x%x\n",
714 1.1 pooka Where+i, Data16);
715 1.1 pooka }
716 1.1 pooka #endif
717 1.1 pooka
718 1.1 pooka if (Data16 != 0xffff)
719 1.1 pooka printf("Offset %p not ERASED, wont take.\n",Where+i);
720 1.1 pooka }
721 1.1 pooka }
722 1.1 pooka
723 1.1 pooka /* Specs say to retry if necessary */
724 1.1 pooka for (i = 0; i < 5; i++) {
725 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER);
726 1.1 pooka DELAY(10);
727 1.1 pooka sc->sc_ops->read_uint8(sc,Offset,&Status);
728 1.1 pooka if ((Status & ST_READY)) break;
729 1.1 pooka }
730 1.1 pooka if (0 == (Status & ST_READY)) {
731 1.1 pooka printf("FAILED program_buffer at Location %p, Status= x%x\n",
732 1.1 pooka Offset, Status);
733 1.1 pooka return FALSE;
734 1.1 pooka }
735 1.1 pooka
736 1.1 pooka /* Say how many words we'll be sending */
737 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/2));
738 1.1 pooka
739 1.1 pooka /* Send the data */
740 1.1 pooka for (i = 0; i < sc->sc_buffersize; i+= 2) {
741 1.1 pooka Value = Values[i/2];
742 1.1 pooka sc->sc_ops->write_uint16(sc,Where+i,Value);
743 1.1 pooka DELAY(10);/*jic*/
744 1.1 pooka }
745 1.1 pooka
746 1.1 pooka /* Write confirmation */
747 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM);
748 1.1 pooka
749 1.1 pooka /* Wait until the operation is completed
750 1.1 pooka * Specs say it takes between 800 and 2400 us
751 1.1 pooka * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above.
752 1.1 pooka */
753 1.1 pooka DELAY(800);
754 1.1 pooka
755 1.1 pooka for (i = 0; i < 20; i++) {
756 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS);
757 1.1 pooka sc->sc_ops->read_uint8(sc,Offset,&Status);
758 1.1 pooka if ((Status & ST_READY)) break;
759 1.1 pooka DELAY(200);
760 1.1 pooka }
761 1.1 pooka
762 1.1 pooka ProductIdExit(sc);
763 1.1 pooka
764 1.1 pooka /* Verify? */
765 1.1 pooka if (Verify) {
766 1.1 pooka for (i = 0; i < sc->sc_buffersize; i+= 2) {
767 1.1 pooka sc->sc_ops->read_uint16(sc,Where+i,&Data16);
768 1.1 pooka #ifdef Verbose
769 1.1 pooka if (Verbose) {
770 1.1 pooka printf("Location %p is now x%x\n",
771 1.1 pooka Where+i, Data16);
772 1.1 pooka }
773 1.1 pooka #endif
774 1.1 pooka Value = Values[i/2];
775 1.1 pooka
776 1.1 pooka if ((Data16 != Value)) {
777 1.1 pooka PrintStatus(Status);
778 1.1 pooka printf(". That didnt work, try again.. [%x != %x]\n",
779 1.1 pooka Data16, Value);
780 1.1 pooka ClearStatusRegister(sc);
781 1.1 pooka return FALSE;
782 1.1 pooka }
783 1.1 pooka }
784 1.1 pooka }
785 1.1 pooka
786 1.1 pooka *nWritten = sc->sc_buffersize;
787 1.1 pooka return TRUE;
788 1.1 pooka }
789 1.1 pooka
790 1.1 pooka /* Write one 32bit word
791 1.1 pooka */
792 1.1 pooka static int
793 1.1 pooka twin_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
794 1.1 pooka int Verify, int *nWritten)
795 1.1 pooka {
796 1.1 pooka uint8_t Status;
797 1.1 pooka uint32_t i, Data32, Value;
798 1.1 pooka uint16_t v0, v1;
799 1.1 pooka
800 1.1 pooka *nWritten = 0;
801 1.1 pooka
802 1.1 pooka v0 = Values[0];
803 1.1 pooka v0 = le16toh(v0);
804 1.1 pooka v1 = Values[1];
805 1.1 pooka v1 = le16toh(v1);
806 1.1 pooka Value = v0 | ((uint32_t)v1 << 16);
807 1.1 pooka if (Verify) {
808 1.1 pooka sc->sc_ops->read_uint32(sc,Offset,&Data32);
809 1.1 pooka #ifdef Verbose
810 1.1 pooka if (Verbose) {
811 1.1 pooka printf("Location %p was x%x\n",
812 1.1 pooka Offset, Data32);
813 1.1 pooka }
814 1.1 pooka #endif
815 1.1 pooka if (Data32 != 0xffffffff)
816 1.1 pooka printf("Offset %p not ERASED, wont take.\n",Offset);
817 1.1 pooka }
818 1.1 pooka
819 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD);
820 1.1 pooka sc->sc_ops->write_uint32(sc,Offset,Value);
821 1.1 pooka
822 1.1 pooka /* Wait until the operation is completed
823 1.1 pooka * Specs say it takes between 210 and 630 us
824 1.1 pooka * Errata says 360 TYP and Max=TBD (sic)
825 1.1 pooka */
826 1.1 pooka DELAY(400);
827 1.1 pooka
828 1.1 pooka for (i = 0; i < 10; i++) {
829 1.1 pooka sc->sc_ops->read_uint8(sc,Offset,&Status);
830 1.1 pooka if ((Status & ST_READY)) break;
831 1.1 pooka DELAY(100);
832 1.1 pooka }
833 1.1 pooka
834 1.1 pooka ProductIdExit(sc);
835 1.1 pooka
836 1.1 pooka if (Verify) {
837 1.1 pooka sc->sc_ops->read_uint32(sc,Offset,&Data32);
838 1.1 pooka #ifdef Verbose
839 1.1 pooka if (Verbose) {
840 1.1 pooka printf("Location %p is now x%x\n",
841 1.1 pooka Offset, Data32);
842 1.1 pooka }
843 1.1 pooka #endif
844 1.1 pooka if ((Data32 != Value)) {
845 1.1 pooka PrintStatus(Status);
846 1.1 pooka printf(". That didnt work, try again.. [%x != %x]\n",
847 1.1 pooka Data32, Value);
848 1.1 pooka ClearStatusRegister(sc);
849 1.1 pooka return FALSE;
850 1.1 pooka }
851 1.1 pooka }
852 1.1 pooka
853 1.1 pooka *nWritten = 4;
854 1.1 pooka return TRUE;
855 1.1 pooka }
856 1.1 pooka
857 1.1 pooka /* Write one buffer, 32bit words at a time
858 1.1 pooka */
859 1.1 pooka static int
860 1.1 pooka twin_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
861 1.1 pooka int Verify, int *nWritten)
862 1.1 pooka {
863 1.1 pooka uint8_t Status;
864 1.1 pooka uint32_t i, Data32, Value;
865 1.1 pooka uint16_t v0 = 0, v1;
866 1.1 pooka volatile uint8_t *Where = Offset;
867 1.1 pooka
868 1.1 pooka *nWritten = 0;
869 1.1 pooka if (sc->sc_buffersize == 0)
870 1.1 pooka return FALSE; /* sanity */
871 1.1 pooka
872 1.1 pooka if (Verify) {
873 1.1 pooka for (i = 0; i < sc->sc_buffersize; i+= 4) {
874 1.1 pooka sc->sc_ops->read_uint32(sc,Where+i,&Data32);
875 1.1 pooka #ifdef Verbose
876 1.1 pooka if (Verbose) {
877 1.1 pooka printf("Location %p was x%x\n",
878 1.1 pooka Where+i, Data32);
879 1.1 pooka }
880 1.1 pooka #endif
881 1.1 pooka if (Data32 != 0xffffffff)
882 1.1 pooka printf("Offset %p not ERASED, wont take.\n",Where+i);
883 1.1 pooka }
884 1.1 pooka }
885 1.1 pooka
886 1.1 pooka /* Specs say to retry if necessary */
887 1.1 pooka for (i = 0; i < 5; i++) {
888 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER);
889 1.1 pooka DELAY(10);
890 1.1 pooka sc->sc_ops->read_uint8(sc,Offset,&Status);
891 1.1 pooka if ((Status & ST_READY)) break;
892 1.1 pooka }
893 1.1 pooka if (0 == (Status & ST_READY)) {
894 1.1 pooka printf("FAILED program_buffer at Location %p, Status= x%x\n",
895 1.1 pooka Offset, Status);
896 1.1 pooka return FALSE;
897 1.1 pooka }
898 1.1 pooka
899 1.1 pooka /* Say how many words we'll be sending */
900 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/4)); /* to each twin! */
901 1.1 pooka
902 1.1 pooka /* Send the data */
903 1.1 pooka for (i = 0; i < sc->sc_buffersize; i+= 4) {
904 1.1 pooka v0 = Values[i/2];
905 1.1 pooka v0 = le16toh(v0);
906 1.1 pooka v1 = Values[1+(i/2)];
907 1.1 pooka v1 = le16toh(v1);
908 1.1 pooka Value = v0 | ((uint32_t)v1 << 16);
909 1.1 pooka sc->sc_ops->write_uint32(sc,Where+i,Value);
910 1.1 pooka DELAY(10);/*jic*/
911 1.1 pooka }
912 1.1 pooka
913 1.1 pooka /* Write confirmation */
914 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM);
915 1.1 pooka
916 1.1 pooka /* Wait until the operation is completed
917 1.1 pooka * Specs say it takes between 800 and 2400 us
918 1.1 pooka * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above.
919 1.1 pooka */
920 1.1 pooka DELAY(800);
921 1.1 pooka
922 1.1 pooka for (i = 0; i < 20; i++) {
923 1.1 pooka sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS);
924 1.1 pooka sc->sc_ops->read_uint8(sc,Offset,&Status);
925 1.1 pooka if ((Status & ST_READY)) break;
926 1.1 pooka DELAY(200);
927 1.1 pooka }
928 1.1 pooka
929 1.1 pooka ProductIdExit(sc);
930 1.1 pooka
931 1.1 pooka /* Verify */
932 1.1 pooka if (Verify) {
933 1.1 pooka for (i = 0; i < sc->sc_buffersize; i+= 4) {
934 1.1 pooka sc->sc_ops->read_uint32(sc,Where+i,&Data32);
935 1.1 pooka #ifdef Verbose
936 1.1 pooka if (Verbose) {
937 1.1 pooka printf("Location %p is now x%x\n",
938 1.1 pooka Where+i, Data32);
939 1.1 pooka }
940 1.1 pooka #endif
941 1.1 pooka v0 = Values[i/2];
942 1.1 pooka v0 = le16toh(v0);
943 1.1 pooka v1 = Values[1+(i/2)];
944 1.1 pooka v1 = le16toh(v1);
945 1.1 pooka Value = v0 | ((uint32_t)v1 << 16);
946 1.1 pooka
947 1.1 pooka if ((Data32 != Value)) {
948 1.1 pooka PrintStatus(Status);
949 1.1 pooka printf(". That didnt work, try again.. [%x != %x]\n",
950 1.1 pooka Data32, Value);
951 1.1 pooka ClearStatusRegister(sc);
952 1.1 pooka return FALSE;
953 1.1 pooka }
954 1.1 pooka }
955 1.1 pooka }
956 1.1 pooka
957 1.1 pooka *nWritten = sc->sc_buffersize;
958 1.1 pooka return TRUE;
959 1.1 pooka }
960 1.1 pooka
961 1.1 pooka /* Is there a lock on a given sector
962 1.1 pooka */
963 1.1 pooka static int IsSectorLocked(struct eflash_softc *sc, uint8_t *secptr)
964 1.1 pooka {
965 1.1 pooka uint8_t Data, Data1;
966 1.1 pooka
967 1.1 pooka ProductIdEnter(sc);
968 1.1 pooka /* Lockout info is at address 2 of the given sector, meaning A0=0 A1=1.
969 1.1 pooka */
970 1.1 pooka sc->sc_ops->read_uint8(sc,secptr+(0x0002*2*sc->sc_chips),&Data);
971 1.1 pooka sc->sc_ops->read_uint8(sc,secptr+(0x0003*2*sc->sc_chips),&Data1);
972 1.1 pooka
973 1.1 pooka ProductIdExit(sc);
974 1.1 pooka
975 1.1 pooka return (Data & 1);
976 1.1 pooka }
977 1.1 pooka
978 1.1 pooka /* Remove the write-lock to a sector
979 1.1 pooka */
980 1.1 pooka static void SectorUnLock(struct eflash_softc *sc, uint8_t *secptr)
981 1.1 pooka {
982 1.1 pooka uint8_t Status;
983 1.1 pooka int i;
984 1.1 pooka
985 1.1 pooka DBGME(DEBUG_FUNCS,printf("%s: Unlocking sector %d [ptr %p] ...\n",
986 1.1 pooka device_xname(sc->sc_dev), sc->sc_sector_offset, secptr));
987 1.1 pooka
988 1.1 pooka sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_SET_PREFIX);
989 1.1 pooka sc->sc_ops->write_uint8(sc,secptr,CMD_UNLOCK);
990 1.1 pooka
991 1.1 pooka /* Wait until the unlock is complete.
992 1.1 pooka * Specs say this takes between 64 and 75 usecs.
993 1.1 pooka */
994 1.1 pooka DELAY(100);
995 1.1 pooka
996 1.1 pooka for (i = 0; i < 10; i++) {
997 1.1 pooka sc->sc_ops->read_uint8(sc,secptr,&Status);
998 1.1 pooka if ((Status & ST_READY)) break;
999 1.1 pooka DELAY(100);
1000 1.1 pooka }
1001 1.1 pooka
1002 1.1 pooka ProductIdExit(sc);
1003 1.1 pooka
1004 1.1 pooka if ((Status & ST_MASK) == ST_READY) {
1005 1.1 pooka DBGME(DEBUG_FUNCS,printf("%s: Unlocked ok.\n",
1006 1.1 pooka device_xname(sc->sc_dev)));
1007 1.1 pooka return;
1008 1.1 pooka }
1009 1.1 pooka
1010 1.1 pooka PrintStatus(Status);
1011 1.1 pooka DBGME(DEBUG_ERRORS,printf("%s: Unlock of sector %d NOT completed (status=%x).\n",
1012 1.1 pooka device_xname(sc->sc_dev),
1013 1.1 pooka sc->sc_sector_offset, Status));
1014 1.1 pooka ClearStatusRegister(sc);
1015 1.1 pooka }
1016 1.1 pooka
1017 1.1 pooka
1018 1.1 pooka /* Erase one sector
1019 1.1 pooka */
1020 1.1 pooka static int SectorErase(struct eflash_softc *sc, void *secptr)
1021 1.1 pooka {
1022 1.1 pooka uint8_t Status = 0;
1023 1.1 pooka uint16_t i;
1024 1.1 pooka
1025 1.1 pooka DBGME(DEBUG_FUNCS,printf("%s: Erasing sector %d [ptr %p] ...\n",
1026 1.1 pooka device_xname(sc->sc_dev), sc->sc_sector_offset, secptr));
1027 1.1 pooka
1028 1.1 pooka /* On some chips we just cannot avoid the locking business.
1029 1.1 pooka */
1030 1.1 pooka if ((sc->sc_chips == 1) &&
1031 1.1 pooka IsSectorLocked(sc,secptr))
1032 1.1 pooka SectorUnLock(sc,secptr);
1033 1.1 pooka
1034 1.1 pooka sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_SETUP);
1035 1.1 pooka sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_CONFIRM);
1036 1.1 pooka
1037 1.1 pooka /* Wait until the erase is actually completed
1038 1.1 pooka * Specs say it will take between 1 and 5 seconds.
1039 1.1 pooka * Errata says it takes 2 sec min and 25 sec max.
1040 1.1 pooka * Double that before giving up.
1041 1.1 pooka */
1042 1.1 pooka for (i = 0; i < 20; i++) {
1043 1.1 pooka /* Sleep for at least 2 seconds
1044 1.1 pooka */
1045 1.1 pooka tsleep(sc,PWAIT,"erase", hz * 2);
1046 1.1 pooka
1047 1.1 pooka sc->sc_ops->read_uint8(sc,secptr,&Status);
1048 1.1 pooka if ((Status & ST_READY)) break;
1049 1.1 pooka PrintStatus(Status);
1050 1.1 pooka }
1051 1.1 pooka
1052 1.1 pooka ProductIdExit(sc);
1053 1.1 pooka
1054 1.1 pooka if ((Status & ST_ERASE_MASK) == ST_READY) {
1055 1.1 pooka DBGME(DEBUG_FUNCS,printf("%s: Erased ok.\n", device_xname(sc->sc_dev)));
1056 1.1 pooka return 0;
1057 1.1 pooka }
1058 1.1 pooka
1059 1.1 pooka PrintStatus(Status);
1060 1.1 pooka DBGME(DEBUG_ERRORS,printf("%s: Erase of sector %d NOT completed (status=%x).\n",
1061 1.1 pooka device_xname(sc->sc_dev),
1062 1.1 pooka sc->sc_sector_offset, Status));
1063 1.1 pooka
1064 1.1 pooka ClearStatusRegister(sc);
1065 1.1 pooka return EIO;
1066 1.1 pooka }
1067 1.1 pooka
1068 1.1 pooka
1069 1.1 pooka
1070 1.1 pooka /* Write (a portion of) a sector
1071 1.1 pooka */
1072 1.1 pooka static size_t eflash_write_sector(struct eflash_softc *sc, char *Buffer, size_t n,
1073 1.1 pooka uint8_t *Offset, int Verify)
1074 1.1 pooka {
1075 1.1 pooka size_t i;
1076 1.1 pooka
1077 1.1 pooka /* Make sure the device is not screwed up
1078 1.1 pooka */
1079 1.1 pooka if (IsIrresponsive(sc)) {
1080 1.1 pooka printf("FLASH is locked-up (or mapped cacheable?), wont work. ");
1081 1.1 pooka }
1082 1.1 pooka
1083 1.1 pooka for (i = 0; i < n;) {
1084 1.1 pooka int nTries;
1085 1.1 pooka int nWritten = 0;/*we expect 2 or 4 */
1086 1.1 pooka
1087 1.1 pooka if (sc->sc_buffersize && ((n-i) >= sc->sc_buffersize)) {
1088 1.1 pooka for (nTries = 0; nTries < 5; nTries++)
1089 1.1 pooka if (sc->sc_ops->program_buffer(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten))
1090 1.1 pooka break;
1091 1.1 pooka } else {
1092 1.1 pooka for (nTries = 0; nTries < 5; nTries++)
1093 1.1 pooka if (sc->sc_ops->program_word(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten))
1094 1.1 pooka break;
1095 1.1 pooka }
1096 1.1 pooka Offset += nWritten;
1097 1.1 pooka i += nWritten;
1098 1.1 pooka if (nWritten == 0)
1099 1.1 pooka break;
1100 1.1 pooka }
1101 1.1 pooka return i;
1102 1.1 pooka }
1103 1.1 pooka
1104 1.1 pooka /* Identify type and the sector map of the FLASH.
1105 1.1 pooka * Argument is the base address of the device and the count of chips on the bus (1/2)
1106 1.1 pooka * Returns FALSE if failed
1107 1.1 pooka */
1108 1.1 pooka static const struct flash_ops single_ops = {
1109 1.1 pooka single_write_uint8,
1110 1.1 pooka single_read_uint8,
1111 1.1 pooka single_write_uint16,
1112 1.1 pooka single_read_uint16,
1113 1.1 pooka single_write_uint32,
1114 1.1 pooka single_read_uint32,
1115 1.1 pooka single_program_word,
1116 1.1 pooka single_program_buffer
1117 1.1 pooka };
1118 1.1 pooka
1119 1.1 pooka static const struct flash_ops twin_ops = {
1120 1.1 pooka twin_write_uint8,
1121 1.1 pooka twin_read_uint8,
1122 1.1 pooka twin_write_uint16,
1123 1.1 pooka twin_read_uint16,
1124 1.1 pooka twin_write_uint32,
1125 1.1 pooka twin_read_uint32,
1126 1.1 pooka twin_program_word,
1127 1.1 pooka twin_program_buffer
1128 1.1 pooka };
1129 1.1 pooka
1130 1.1 pooka static int flash_identify(struct eflash_softc *sc)
1131 1.1 pooka {
1132 1.1 pooka uint8_t Mid, Did;
1133 1.1 pooka int i;
1134 1.1 pooka
1135 1.1 pooka if (sc->sc_chips > 1)
1136 1.1 pooka sc->sc_ops = &twin_ops;
1137 1.1 pooka else
1138 1.1 pooka sc->sc_ops = &single_ops;
1139 1.1 pooka
1140 1.1 pooka sc->sc_buffersize = 0;
1141 1.1 pooka #if USE_BUFFERED_WRITES
1142 1.1 pooka sc->sc_buffersize = BUFFER_BYTES * sc->sc_chips;
1143 1.1 pooka #endif
1144 1.1 pooka sc->sc_sector = NULL;
1145 1.1 pooka sc->sc_sector_size = 0;
1146 1.1 pooka sc->sc_sector_offset = NOSECTOR;
1147 1.1 pooka sc->sc_erased = FALSE;
1148 1.1 pooka
1149 1.1 pooka ProductIdEnter(sc);
1150 1.1 pooka sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0000*2*sc->sc_chips),&Mid);
1151 1.1 pooka sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0001*2*sc->sc_chips),&Did);
1152 1.1 pooka ProductIdExit(sc);
1153 1.1 pooka
1154 1.1 pooka sc->sc_type.ft_manuf_code = Mid;
1155 1.1 pooka sc->sc_type.ft_device_code = Did;
1156 1.1 pooka
1157 1.1 pooka for (i = 0; i < nMAPS; i++) {
1158 1.1 pooka if ((sector_maps[i].ft_manuf_code == Mid) && (sector_maps[i].ft_device_code == Did)) {
1159 1.1 pooka int j;
1160 1.1 pooka uint32_t ms = 0;
1161 1.1 pooka sc->sc_type = sector_maps[i];
1162 1.1 pooka /* double the sector sizes if twin-chips */
1163 1.1 pooka for (j = 0; j < nDELTAS; j++) {
1164 1.1 pooka sc->sc_type.ft_deltas[j].nKB *= sc->sc_chips;
1165 1.1 pooka if (ms < sc->sc_type.ft_deltas[j].nKB)
1166 1.1 pooka ms = sc->sc_type.ft_deltas[j].nKB;
1167 1.1 pooka }
1168 1.1 pooka sc->sc_max_secsize = ms * 1024;
1169 1.1 pooka return TRUE;
1170 1.1 pooka }
1171 1.1 pooka }
1172 1.1 pooka
1173 1.1 pooka return FALSE;
1174 1.1 pooka }
1175 1.1 pooka
1176 1.1 pooka /* Common code for read&write argument validation
1177 1.1 pooka */
1178 1.1 pooka static int eflash_validate(struct eflash_softc *sc, daddr_t start, size_t *pSize, void **pSrc)
1179 1.1 pooka {
1180 1.1 pooka daddr_t Size;
1181 1.1 pooka uint32_t sec;
1182 1.1 pooka size_t secsize, secstart;
1183 1.1 pooka
1184 1.1 pooka /* Validate args
1185 1.1 pooka */
1186 1.1 pooka if (start >= sc->sc_capacity) {
1187 1.1 pooka *pSize = 0;
1188 1.1 pooka DBGME(DEBUG_ERRORS,printf("eflash::ValidateArg(%qx) EOF\n", start));
1189 1.1 pooka return E2BIG;
1190 1.1 pooka }
1191 1.1 pooka
1192 1.1 pooka /* Map sector if not already
1193 1.1 pooka */
1194 1.1 pooka sec = SectorNumber(&sc->sc_type, start << DEV_BSHIFT);
1195 1.1 pooka secsize = SectorSize( &sc->sc_type, sec);
1196 1.1 pooka secstart = SectorStart(&sc->sc_type,sec);
1197 1.1 pooka if (sec != sc->sc_sector_offset) {
1198 1.1 pooka int error;
1199 1.1 pooka
1200 1.1 pooka /* unmap previous first */
1201 1.1 pooka if (sc->sc_sector_offset != NOSECTOR) {
1202 1.1 pooka DBGME(DEBUG_FUNCS,printf("%s: unmap %p %zx\n",
1203 1.1 pooka device_xname(sc->sc_dev), sc->sc_sector, sc->sc_sector_size));
1204 1.1 pooka iounaccess((vaddr_t)sc->sc_sector, sc->sc_sector_size);
1205 1.1 pooka sc->sc_sector_offset = NOSECTOR;
1206 1.1 pooka }
1207 1.1 pooka
1208 1.1 pooka /* map new */
1209 1.1 pooka error = ioaccess((vaddr_t)sc->sc_sector,
1210 1.1 pooka secstart + sc->sc_base,
1211 1.1 pooka secsize);
1212 1.2 tsutsui DBGME(DEBUG_FUNCS,printf("%s: mapped %p %zx -> %zx %d\n",
1213 1.1 pooka device_xname(sc->sc_dev),
1214 1.1 pooka sc->sc_sector, secsize, secstart + sc->sc_base,error));
1215 1.1 pooka if (error) return error;
1216 1.1 pooka
1217 1.1 pooka /* Update state. We have to assume the sector was not erased. Sigh. */
1218 1.1 pooka sc->sc_sector_offset = sec;
1219 1.1 pooka sc->sc_sector_size = secsize;
1220 1.1 pooka sc->sc_erased = FALSE;
1221 1.1 pooka }
1222 1.1 pooka
1223 1.1 pooka /* Adjust size if necessary
1224 1.1 pooka */
1225 1.1 pooka Size = start + *pSize; /* last sector */
1226 1.1 pooka if (Size > sc->sc_capacity) {
1227 1.1 pooka /* At most this many sectors
1228 1.1 pooka */
1229 1.1 pooka Size = sc->sc_capacity - start;
1230 1.1 pooka *pSize = (size_t)Size;
1231 1.1 pooka }
1232 1.1 pooka if (*pSize > (secsize >> DEV_BSHIFT)) {
1233 1.1 pooka *pSize = secsize >> DEV_BSHIFT;
1234 1.1 pooka }
1235 1.1 pooka
1236 1.1 pooka *pSrc = sc->sc_sector + (start << DEV_BSHIFT) - secstart;
1237 1.1 pooka
1238 1.1 pooka DBGME(DEBUG_FUNCS,printf("%s: Validate %qx %zd %p\n",
1239 1.1 pooka device_xname(sc->sc_dev), start,*pSize, *pSrc));
1240 1.1 pooka return 0;
1241 1.1 pooka }
1242 1.1 pooka
1243 1.1 pooka static int eflash_read_at (struct eflash_softc *sc,
1244 1.1 pooka daddr_t start_sector, char *buffer, size_t nblocks,
1245 1.1 pooka size_t * pSizeRead)
1246 1.1 pooka {
1247 1.1 pooka int error;
1248 1.1 pooka uint32_t SizeRead = 0;
1249 1.1 pooka void *src;
1250 1.1 pooka
1251 1.1 pooka DBGME(DEBUG_XFERS|DEBUG_READS,printf("%s: EflashReadAt(%qx %p %zd %p)\n",
1252 1.1 pooka device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeRead));
1253 1.1 pooka
1254 1.1 pooka /* Validate & trim arguments
1255 1.1 pooka */
1256 1.1 pooka error = eflash_validate(sc, start_sector, &nblocks, &src);
1257 1.1 pooka
1258 1.1 pooka /* Copy data if
1259 1.1 pooka */
1260 1.1 pooka if (error == 0) {
1261 1.1 pooka SizeRead = nblocks;
1262 1.1 pooka memcpy(buffer, src, nblocks << DEV_BSHIFT);
1263 1.1 pooka }
1264 1.1 pooka
1265 1.1 pooka if (pSizeRead)
1266 1.1 pooka *pSizeRead = SizeRead;
1267 1.1 pooka return error;
1268 1.1 pooka }
1269 1.1 pooka
1270 1.1 pooka /* Write SIZE bytes to device.
1271 1.1 pooka */
1272 1.1 pooka static int eflash_write_at (struct eflash_softc *sc,
1273 1.1 pooka daddr_t start_sector, char *buffer, size_t nblocks,
1274 1.1 pooka size_t * pSizeWritten)
1275 1.1 pooka {
1276 1.1 pooka int error;
1277 1.1 pooka void *src;
1278 1.1 pooka size_t SizeWritten = 0;
1279 1.1 pooka
1280 1.1 pooka DBGME(DEBUG_XFERS|DEBUG_WRITES,printf("%s: EflashWriteAt(%qx %p %zd %p)\n",
1281 1.1 pooka device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeWritten));
1282 1.1 pooka
1283 1.1 pooka /* Validate & trim arguments
1284 1.1 pooka */
1285 1.1 pooka error = eflash_validate(sc, start_sector, &nblocks, &src);
1286 1.1 pooka
1287 1.1 pooka if (error == 0) {
1288 1.1 pooka /* Do we have to erase it */
1289 1.1 pooka if (! sc->sc_erased) {
1290 1.1 pooka
1291 1.1 pooka error = SectorErase(sc,src);
1292 1.1 pooka if (error)
1293 1.1 pooka goto Out;
1294 1.1 pooka sc->sc_erased = TRUE;
1295 1.1 pooka }
1296 1.1 pooka SizeWritten = eflash_write_sector(sc, buffer, nblocks << DEV_BSHIFT, src, TRUE);
1297 1.1 pooka SizeWritten >>= DEV_BSHIFT;
1298 1.1 pooka }
1299 1.1 pooka
1300 1.1 pooka Out:
1301 1.1 pooka if (pSizeWritten)
1302 1.1 pooka *pSizeWritten = SizeWritten;
1303 1.1 pooka return error;
1304 1.1 pooka }
1305 1.1 pooka
1306 1.1 pooka /* Rest of code lifted with mods from the dev\ata\wd.c driver
1307 1.1 pooka */
1308 1.1 pooka
1309 1.3 tls /* $NetBSD: flash_ebus.c,v 1.3 2011/11/19 22:51:19 tls Exp $ */
1310 1.1 pooka
1311 1.1 pooka /*
1312 1.1 pooka * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
1313 1.1 pooka *
1314 1.1 pooka * Redistribution and use in source and binary forms, with or without
1315 1.1 pooka * modification, are permitted provided that the following conditions
1316 1.1 pooka * are met:
1317 1.1 pooka * 1. Redistributions of source code must retain the above copyright
1318 1.1 pooka * notice, this list of conditions and the following disclaimer.
1319 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
1320 1.1 pooka * notice, this list of conditions and the following disclaimer in the
1321 1.1 pooka * documentation and/or other materials provided with the distribution.
1322 1.1 pooka * 3. All advertising materials mentioning features or use of this software
1323 1.1 pooka * must display the following acknowledgement:
1324 1.1 pooka * This product includes software developed by Manuel Bouyer.
1325 1.1 pooka * 4. The name of the author may not be used to endorse or promote products
1326 1.1 pooka * derived from this software without specific prior written permission.
1327 1.1 pooka *
1328 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1329 1.1 pooka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1330 1.1 pooka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1331 1.1 pooka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1332 1.1 pooka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1333 1.1 pooka * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1334 1.1 pooka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1335 1.1 pooka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1336 1.1 pooka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1337 1.1 pooka * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1338 1.1 pooka */
1339 1.1 pooka
1340 1.1 pooka /*-
1341 1.1 pooka * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
1342 1.1 pooka * All rights reserved.
1343 1.1 pooka *
1344 1.1 pooka * This code is derived from software contributed to The NetBSD Foundation
1345 1.1 pooka * by Charles M. Hannum and by Onno van der Linden.
1346 1.1 pooka *
1347 1.1 pooka * Redistribution and use in source and binary forms, with or without
1348 1.1 pooka * modification, are permitted provided that the following conditions
1349 1.1 pooka * are met:
1350 1.1 pooka * 1. Redistributions of source code must retain the above copyright
1351 1.1 pooka * notice, this list of conditions and the following disclaimer.
1352 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
1353 1.1 pooka * notice, this list of conditions and the following disclaimer in the
1354 1.1 pooka * documentation and/or other materials provided with the distribution.
1355 1.1 pooka * 3. All advertising materials mentioning features or use of this software
1356 1.1 pooka * must display the following acknowledgement:
1357 1.1 pooka * This product includes software developed by the NetBSD
1358 1.1 pooka * Foundation, Inc. and its contributors.
1359 1.1 pooka * 4. Neither the name of The NetBSD Foundation nor the names of its
1360 1.1 pooka * contributors may be used to endorse or promote products derived
1361 1.1 pooka * from this software without specific prior written permission.
1362 1.1 pooka *
1363 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1364 1.1 pooka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1365 1.1 pooka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1366 1.1 pooka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
1367 1.1 pooka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1368 1.1 pooka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1369 1.1 pooka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1370 1.1 pooka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1371 1.1 pooka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1372 1.1 pooka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1373 1.1 pooka * POSSIBILITY OF SUCH DAMAGE.
1374 1.1 pooka */
1375 1.1 pooka
1376 1.1 pooka static const char ST506[] = "ST506";
1377 1.1 pooka
1378 1.1 pooka #define EFLASHIORETRIES_SINGLE 4 /* number of retries before single-sector */
1379 1.1 pooka #define EFLASHIORETRIES 5 /* number of retries before giving up */
1380 1.1 pooka #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */
1381 1.1 pooka
1382 1.1 pooka #define EFLASHUNIT(dev) DISKUNIT(dev)
1383 1.1 pooka #define EFLASHPART(dev) DISKPART(dev)
1384 1.1 pooka #define EFLASHMINOR(unit, part) DISKMINOR(unit, part)
1385 1.1 pooka #define MAKEEFLASHDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
1386 1.1 pooka
1387 1.1 pooka #define EFLASHLABELDEV(dev) (MAKEEFLASHDEV(major(dev), EFLASHUNIT(dev), RAW_PART))
1388 1.1 pooka
1389 1.1 pooka void eflashperror(const struct eflash_softc *);
1390 1.1 pooka
1391 1.1 pooka extern struct cfdriver eflash_cd;
1392 1.1 pooka
1393 1.1 pooka dev_type_open(eflashopen);
1394 1.1 pooka dev_type_close(eflashclose);
1395 1.1 pooka dev_type_read(eflashread);
1396 1.1 pooka dev_type_write(eflashwrite);
1397 1.1 pooka dev_type_ioctl(eflashioctl);
1398 1.1 pooka dev_type_strategy(eflashstrategy);
1399 1.1 pooka dev_type_dump(eflashdump);
1400 1.1 pooka dev_type_size(eflashsize);
1401 1.1 pooka
1402 1.1 pooka const struct bdevsw eflash_bdevsw = {
1403 1.1 pooka eflashopen, eflashclose, eflashstrategy, eflashioctl, eflashdump, eflashsize, D_DISK
1404 1.1 pooka };
1405 1.1 pooka
1406 1.1 pooka const struct cdevsw eflash_cdevsw = {
1407 1.1 pooka eflashopen, eflashclose, eflashread, eflashwrite, eflashioctl,
1408 1.1 pooka nostop, notty, nopoll, nommap, nokqfilter, D_DISK
1409 1.1 pooka };
1410 1.1 pooka
1411 1.1 pooka void eflashgetdefaultlabel(struct eflash_softc *, struct disklabel *);
1412 1.1 pooka void eflashgetdisklabel(struct eflash_softc *);
1413 1.1 pooka void eflashstart(void *);
1414 1.1 pooka void __eflashstart(struct eflash_softc*, struct buf *);
1415 1.1 pooka void eflashrestart(void *);
1416 1.1 pooka void eflashattach(struct eflash_softc *);
1417 1.1 pooka int eflashdetach(struct device *, int);
1418 1.1 pooka int eflashactivate(struct device *, enum devact);
1419 1.1 pooka
1420 1.1 pooka void eflashdone(struct eflash_softc *);
1421 1.1 pooka static void eflash_params_to_properties(struct eflash_softc *sc);
1422 1.1 pooka
1423 1.1 pooka struct dkdriver eflashdkdriver = { eflashstrategy, minphys };
1424 1.1 pooka
1425 1.1 pooka #ifdef HAS_BAD144_HANDLING
1426 1.1 pooka static void bad144intern(struct eflash_softc *);
1427 1.1 pooka #endif
1428 1.1 pooka
1429 1.1 pooka static void eflash_wedges(void *arg);
1430 1.1 pooka
1431 1.1 pooka void
1432 1.1 pooka eflashattach(struct eflash_softc *sc)
1433 1.1 pooka {
1434 1.1 pooka struct device *self = sc->sc_dev;
1435 1.1 pooka char pbuf[9];
1436 1.1 pooka DEBUG_PRINT(("%s: eflashattach\n", device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE);
1437 1.1 pooka
1438 1.1 pooka callout_init(&sc->sc_restart_ch, 0);
1439 1.1 pooka bufq_alloc(&sc->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
1440 1.1 pooka
1441 1.1 pooka sc->openings = 1; /* wazziz?*/
1442 1.1 pooka
1443 1.1 pooka aprint_naive("\n");
1444 1.1 pooka
1445 1.1 pooka /* setup all required fields so that if the attach fails we are ok */
1446 1.1 pooka sc->sc_dk.dk_driver = &eflashdkdriver;
1447 1.1 pooka sc->sc_dk.dk_name = device_xname(sc->sc_dev);
1448 1.1 pooka
1449 1.1 pooka format_bytes(pbuf, sizeof(pbuf), sc->sc_capacity * DEV_BSIZE);
1450 1.1 pooka aprint_normal("%s: %s, %d cyl, %d head, %d sec, %d bytes/sect x %llu sectors\n",
1451 1.1 pooka self->dv_xname, pbuf, 1, 1, sc->sc_capacity,
1452 1.1 pooka DEV_BSIZE, (unsigned long long)sc->sc_capacity);
1453 1.1 pooka
1454 1.1 pooka eflash_params_to_properties(sc);
1455 1.1 pooka
1456 1.1 pooka /*
1457 1.1 pooka * Attach the disk structure. We fill in dk_info later.
1458 1.1 pooka */
1459 1.1 pooka disk_attach(&sc->sc_dk);
1460 1.1 pooka
1461 1.1 pooka #if NRND > 0
1462 1.1 pooka rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
1463 1.1 pooka RND_TYPE_DISK, 0);
1464 1.1 pooka #endif
1465 1.1 pooka
1466 1.1 pooka }
1467 1.1 pooka
1468 1.1 pooka int
1469 1.1 pooka eflashactivate(struct device *self, enum devact act)
1470 1.1 pooka {
1471 1.1 pooka int rv = 0;
1472 1.1 pooka
1473 1.1 pooka DEBUG_PRINT(("eflashactivate %x\n", act), DEBUG_FUNCS | DEBUG_PROBE);
1474 1.1 pooka
1475 1.1 pooka switch (act) {
1476 1.1 pooka case DVACT_DEACTIVATE:
1477 1.1 pooka /*
1478 1.1 pooka * Nothing to do; we key off the device's DVF_ACTIVATE.
1479 1.1 pooka */
1480 1.1 pooka break;
1481 1.1 pooka default:
1482 1.1 pooka rv = EOPNOTSUPP;
1483 1.1 pooka break;
1484 1.1 pooka }
1485 1.1 pooka return (rv);
1486 1.1 pooka }
1487 1.1 pooka
1488 1.1 pooka int
1489 1.1 pooka eflashdetach(struct device *self, int flags)
1490 1.1 pooka {
1491 1.1 pooka struct eflash_softc *sc = device_private(self);
1492 1.1 pooka int s, bmaj, cmaj, i, mn;
1493 1.1 pooka
1494 1.1 pooka DEBUG_PRINT(("%s: eflashdetach\n", device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE);
1495 1.1 pooka
1496 1.1 pooka /* locate the major number */
1497 1.1 pooka bmaj = bdevsw_lookup_major(&eflash_bdevsw);
1498 1.1 pooka cmaj = cdevsw_lookup_major(&eflash_cdevsw);
1499 1.1 pooka
1500 1.1 pooka /* Nuke the vnodes for any open instances. */
1501 1.1 pooka for (i = 0; i < MAXPARTITIONS; i++) {
1502 1.1 pooka mn = EFLASHMINOR(device_unit(self), i);
1503 1.1 pooka vdevgone(bmaj, mn, mn, VBLK);
1504 1.1 pooka vdevgone(cmaj, mn, mn, VCHR);
1505 1.1 pooka }
1506 1.1 pooka
1507 1.1 pooka /* Delete all of our wedges. */
1508 1.1 pooka dkwedge_delall(&sc->sc_dk);
1509 1.1 pooka
1510 1.1 pooka s = splbio();
1511 1.1 pooka
1512 1.1 pooka /* Kill off any queued buffers. */
1513 1.1 pooka bufq_drain(sc->sc_q);
1514 1.1 pooka
1515 1.1 pooka bufq_free(sc->sc_q);
1516 1.1 pooka /*sc->atabus->ata_killpending(sc->drvp);*/
1517 1.1 pooka
1518 1.1 pooka splx(s);
1519 1.1 pooka
1520 1.1 pooka /* Detach disk. */
1521 1.1 pooka disk_detach(&sc->sc_dk);
1522 1.1 pooka
1523 1.1 pooka #if NRND > 0
1524 1.1 pooka /* Unhook the entropy source. */
1525 1.1 pooka rnd_detach_source(&sc->rnd_source);
1526 1.1 pooka #endif
1527 1.1 pooka
1528 1.1 pooka /*sc->drvp->drive_flags = 0; -- no drive any more here */
1529 1.1 pooka
1530 1.1 pooka return (0);
1531 1.1 pooka }
1532 1.1 pooka
1533 1.1 pooka extern int dkwedge_autodiscover;
1534 1.1 pooka
1535 1.1 pooka /* Aux temp thread to avoid deadlock when doing the partitio.. ahem wedges thing.
1536 1.1 pooka */
1537 1.1 pooka static void
1538 1.1 pooka eflash_wedges(void *arg)
1539 1.1 pooka {
1540 1.1 pooka struct eflash_softc *sc = (struct eflash_softc*)arg;
1541 1.1 pooka
1542 1.1 pooka DBGME(DEBUG_STATUS,printf("%s: wedges started for %p\n", sc->sc_dk.dk_name, sc));
1543 1.1 pooka
1544 1.1 pooka /* Discover wedges on this disk. */
1545 1.1 pooka dkwedge_autodiscover = 1;
1546 1.1 pooka dkwedge_discover(&sc->sc_dk);
1547 1.1 pooka
1548 1.1 pooka config_pending_decr();
1549 1.1 pooka
1550 1.1 pooka DBGME(DEBUG_STATUS,printf("%s: wedges thread done for %p\n", device_xname(sc->sc_dev), sc));
1551 1.1 pooka kthread_exit(0);
1552 1.1 pooka }
1553 1.1 pooka
1554 1.1 pooka static void
1555 1.1 pooka eflash_thread(void *arg)
1556 1.1 pooka {
1557 1.1 pooka struct eflash_softc *sc = (struct eflash_softc*)arg;
1558 1.1 pooka struct buf *bp;
1559 1.1 pooka vaddr_t addr;
1560 1.1 pooka int s, error;
1561 1.1 pooka
1562 1.1 pooka DBGME(DEBUG_STATUS,printf("%s: thread started for %p\n", device_xname(sc->sc_dev), sc));
1563 1.1 pooka
1564 1.1 pooka s = splbio();
1565 1.1 pooka eflashattach(sc);
1566 1.1 pooka splx(s);
1567 1.1 pooka
1568 1.1 pooka /* Allocate a VM window large enough to map the largest sector
1569 1.1 pooka * BUGBUG We could risk it and allocate/free on open/close?
1570 1.1 pooka */
1571 1.1 pooka addr = uvm_km_alloc(kernel_map, sc->sc_max_secsize, 0, UVM_KMF_VAONLY);
1572 1.1 pooka if (addr == 0)
1573 1.1 pooka panic("eflash_thread: kernel map full (%lx)", (long unsigned)sc->sc_max_secsize);
1574 1.1 pooka sc->sc_sector = (/*volatile*/ uint8_t *) addr;
1575 1.1 pooka sc->sc_sector_size = 0;
1576 1.1 pooka sc->sc_sector_offset = NOSECTOR;
1577 1.1 pooka
1578 1.1 pooka error = kthread_create(PRI_NONE, 0, NULL,
1579 1.1 pooka eflash_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev));
1580 1.1 pooka if (error) {
1581 1.1 pooka aprint_error_dev(sc->sc_dev, "wedges: unable to create kernel "
1582 1.1 pooka "thread: error %d\n", error);
1583 1.1 pooka /* XXX: why continue? */
1584 1.1 pooka }
1585 1.1 pooka
1586 1.1 pooka
1587 1.1 pooka DBGME(DEBUG_STATUS,printf("%s: thread service active for %p\n", device_xname(sc->sc_dev), sc));
1588 1.1 pooka
1589 1.1 pooka s = splbio();
1590 1.1 pooka for (;;) {
1591 1.1 pooka /* Get next I/O request, wait if necessary
1592 1.1 pooka */
1593 1.1 pooka if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 &&
1594 1.1 pooka (sc->active_xfer == NULL)) {
1595 1.1 pooka sc->ch_flags &= ~ATACH_TH_RUN;
1596 1.1 pooka (void) tsleep(&sc->ch_thread, PRIBIO, "eflashth", 0);
1597 1.1 pooka sc->ch_flags |= ATACH_TH_RUN;
1598 1.1 pooka }
1599 1.1 pooka if (sc->ch_flags & ATACH_SHUTDOWN) {
1600 1.1 pooka break;
1601 1.1 pooka }
1602 1.1 pooka bp = sc->active_xfer;
1603 1.1 pooka sc->active_xfer = NULL;
1604 1.1 pooka if (bp != NULL) {
1605 1.1 pooka
1606 1.1 pooka size_t sz = DEV_BSIZE, bnow;
1607 1.1 pooka
1608 1.1 pooka DBGME(DEBUG_XFERS,printf("%s: task %p %x %p %qx %d (%zd)\n", device_xname(sc->sc_dev), bp,
1609 1.1 pooka sc->sc_bio.flags, sc->sc_bio.databuf, sc->sc_bio.blkno,
1610 1.1 pooka sc->sc_bio.nbytes, sc->sc_bio.nblks));
1611 1.1 pooka
1612 1.1 pooka sc->sc_bio.error = 0;
1613 1.1 pooka for (; sc->sc_bio.nblks > 0;) {
1614 1.1 pooka
1615 1.1 pooka bnow = sc->sc_bio.nblks;
1616 1.1 pooka if (sc->sc_bio.flags & ATA_SINGLE) bnow = 1;
1617 1.1 pooka
1618 1.1 pooka if (sc->sc_bio.flags & ATA_READ) {
1619 1.1 pooka sc->sc_bio.error =
1620 1.1 pooka eflash_read_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
1621 1.1 pooka } else {
1622 1.1 pooka sc->sc_bio.error =
1623 1.1 pooka eflash_write_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
1624 1.1 pooka }
1625 1.1 pooka
1626 1.1 pooka if (sc->sc_bio.error)
1627 1.1 pooka break;
1628 1.1 pooka
1629 1.1 pooka sc->sc_bio.blkno += sz; /* in blocks */
1630 1.1 pooka sc->sc_bio.nblks -= sz;
1631 1.1 pooka sc->sc_bio.blkdone += sz;
1632 1.1 pooka sz = sz << DEV_BSHIFT; /* in bytes */
1633 1.1 pooka sc->sc_bio.databuf += sz;
1634 1.1 pooka sc->sc_bio.nbytes -= sz;
1635 1.1 pooka }
1636 1.1 pooka
1637 1.1 pooka eflashdone(sc);
1638 1.1 pooka }
1639 1.1 pooka }
1640 1.1 pooka
1641 1.1 pooka splx(s);
1642 1.1 pooka sc->ch_thread = NULL;
1643 1.1 pooka wakeup(&sc->ch_flags);
1644 1.1 pooka
1645 1.1 pooka DBGME(DEBUG_STATUS,printf("%s: thread service terminated for %p\n", device_xname(sc->sc_dev), sc));
1646 1.1 pooka
1647 1.1 pooka kthread_exit(0);
1648 1.1 pooka }
1649 1.1 pooka
1650 1.1 pooka
1651 1.1 pooka /*
1652 1.1 pooka * Read/write routine for a buffer. Validates the arguments and schedules the
1653 1.1 pooka * transfer. Does not wait for the transfer to complete.
1654 1.1 pooka */
1655 1.1 pooka void
1656 1.1 pooka eflashstrategy(struct buf *bp)
1657 1.1 pooka {
1658 1.1 pooka struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(bp->b_dev));
1659 1.1 pooka struct disklabel *lp = sc->sc_dk.dk_label;
1660 1.1 pooka daddr_t blkno;
1661 1.1 pooka int s;
1662 1.1 pooka
1663 1.1 pooka DEBUG_PRINT(("%s: eflashstrategy %lld\n", device_xname(sc->sc_dev), bp->b_blkno),
1664 1.1 pooka DEBUG_XFERS);
1665 1.1 pooka
1666 1.1 pooka /* Valid request? */
1667 1.1 pooka if (bp->b_blkno < 0 ||
1668 1.1 pooka (bp->b_bcount % lp->d_secsize) != 0 ||
1669 1.1 pooka (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
1670 1.1 pooka bp->b_error = EINVAL;
1671 1.1 pooka goto done;
1672 1.1 pooka }
1673 1.1 pooka
1674 1.1 pooka /* If device invalidated (e.g. media change, door open), error. */
1675 1.1 pooka if ((sc->sc_flags & EFLASHF_LOADED) == 0) {
1676 1.1 pooka bp->b_error = EIO;
1677 1.1 pooka goto done;
1678 1.1 pooka }
1679 1.1 pooka
1680 1.1 pooka /* If it's a null transfer, return immediately. */
1681 1.1 pooka if (bp->b_bcount == 0)
1682 1.1 pooka goto done;
1683 1.1 pooka
1684 1.1 pooka /*
1685 1.1 pooka * Do bounds checking, adjust transfer. if error, process.
1686 1.1 pooka * If end of partition, just return.
1687 1.1 pooka */
1688 1.1 pooka if (EFLASHPART(bp->b_dev) == RAW_PART) {
1689 1.1 pooka if (bounds_check_with_mediasize(bp, DEV_BSIZE,
1690 1.1 pooka sc->sc_capacity) <= 0)
1691 1.1 pooka goto done;
1692 1.1 pooka } else {
1693 1.1 pooka if (bounds_check_with_label(&sc->sc_dk, bp,
1694 1.1 pooka (sc->sc_flags & (EFLASHF_WLABEL|EFLASHF_LABELLING)) != 0) <= 0)
1695 1.1 pooka goto done;
1696 1.1 pooka }
1697 1.1 pooka
1698 1.1 pooka /*
1699 1.1 pooka * Now convert the block number to absolute and put it in
1700 1.1 pooka * terms of the device's logical block size.
1701 1.1 pooka */
1702 1.1 pooka if (lp->d_secsize >= DEV_BSIZE)
1703 1.1 pooka blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
1704 1.1 pooka else
1705 1.1 pooka blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
1706 1.1 pooka
1707 1.1 pooka if (EFLASHPART(bp->b_dev) != RAW_PART)
1708 1.1 pooka blkno += lp->d_partitions[EFLASHPART(bp->b_dev)].p_offset;
1709 1.1 pooka
1710 1.1 pooka bp->b_rawblkno = blkno;
1711 1.1 pooka
1712 1.1 pooka /* Queue transfer on drive, activate drive and controller if idle. */
1713 1.1 pooka s = splbio();
1714 1.1 pooka bufq_put(sc->sc_q, bp);
1715 1.1 pooka eflashstart(sc);
1716 1.1 pooka splx(s);
1717 1.1 pooka return;
1718 1.1 pooka done:
1719 1.1 pooka /* Toss transfer; we're done early. */
1720 1.1 pooka bp->b_resid = bp->b_bcount;
1721 1.1 pooka biodone(bp);
1722 1.1 pooka }
1723 1.1 pooka
1724 1.1 pooka /*
1725 1.1 pooka * Queue a drive for I/O.
1726 1.1 pooka */
1727 1.1 pooka void
1728 1.1 pooka eflashstart(void *arg)
1729 1.1 pooka {
1730 1.1 pooka struct eflash_softc *sc = arg;
1731 1.1 pooka struct buf *bp = NULL;
1732 1.1 pooka
1733 1.1 pooka DEBUG_PRINT(("%s: eflashstart\n", device_xname(sc->sc_dev)),
1734 1.1 pooka DEBUG_XFERS);
1735 1.1 pooka while (sc->openings > 0) {
1736 1.1 pooka
1737 1.1 pooka /* Is there a buf for us ? */
1738 1.1 pooka if ((bp = bufq_get(sc->sc_q)) == NULL)
1739 1.1 pooka return;
1740 1.1 pooka
1741 1.1 pooka /*
1742 1.1 pooka * Make the command. First lock the device
1743 1.1 pooka */
1744 1.1 pooka sc->openings--;
1745 1.1 pooka
1746 1.1 pooka sc->retries = 0;
1747 1.1 pooka __eflashstart(sc, bp);
1748 1.1 pooka }
1749 1.1 pooka }
1750 1.1 pooka
1751 1.1 pooka void
1752 1.1 pooka __eflashstart(struct eflash_softc *sc, struct buf *bp)
1753 1.1 pooka {
1754 1.1 pooka DEBUG_PRINT(("%s: __eflashstart %p\n", device_xname(sc->sc_dev), bp),
1755 1.1 pooka DEBUG_XFERS);
1756 1.1 pooka
1757 1.1 pooka sc->sc_bp = bp;
1758 1.1 pooka /*
1759 1.1 pooka * If we're retrying, retry in single-sector mode. This will give us
1760 1.1 pooka * the sector number of the problem, and will eventually allow the
1761 1.1 pooka * transfer to succeed.
1762 1.1 pooka */
1763 1.1 pooka if (sc->retries >= EFLASHIORETRIES_SINGLE)
1764 1.1 pooka sc->sc_bio.flags = ATA_SINGLE;
1765 1.1 pooka else
1766 1.1 pooka sc->sc_bio.flags = 0;
1767 1.1 pooka if (bp->b_flags & B_READ)
1768 1.1 pooka sc->sc_bio.flags |= ATA_READ;
1769 1.1 pooka sc->sc_bio.blkno = bp->b_rawblkno;
1770 1.1 pooka sc->sc_bio.blkdone = 0;
1771 1.1 pooka sc->sc_bio.nbytes = bp->b_bcount;
1772 1.1 pooka sc->sc_bio.nblks = bp->b_bcount >> DEV_BSHIFT;
1773 1.1 pooka sc->sc_bio.databuf = bp->b_data;
1774 1.1 pooka /* Instrumentation. */
1775 1.1 pooka disk_busy(&sc->sc_dk);
1776 1.1 pooka sc->active_xfer = bp;
1777 1.1 pooka wakeup(&sc->ch_thread);
1778 1.1 pooka }
1779 1.1 pooka
1780 1.1 pooka void
1781 1.1 pooka eflashdone(struct eflash_softc *sc)
1782 1.1 pooka {
1783 1.1 pooka struct buf *bp = sc->sc_bp;
1784 1.1 pooka const char *errmsg;
1785 1.1 pooka int do_perror = 0;
1786 1.1 pooka
1787 1.1 pooka DEBUG_PRINT(("%s: eflashdone %p\n", device_xname(sc->sc_dev), bp),
1788 1.1 pooka DEBUG_XFERS);
1789 1.1 pooka
1790 1.1 pooka if (bp == NULL)
1791 1.1 pooka return;
1792 1.1 pooka
1793 1.1 pooka bp->b_resid = sc->sc_bio.nbytes;
1794 1.1 pooka switch (sc->sc_bio.error) {
1795 1.1 pooka case ETIMEDOUT:
1796 1.1 pooka errmsg = "device timeout";
1797 1.1 pooka do_perror = 1;
1798 1.1 pooka goto retry;
1799 1.1 pooka case EBUSY:
1800 1.1 pooka errmsg = "device stuck";
1801 1.1 pooka retry: /* Just reset and retry. Can we do more ? */
1802 1.1 pooka /*eflash_reset(sc);*/
1803 1.1 pooka diskerr(bp, "flash", errmsg, LOG_PRINTF,
1804 1.1 pooka sc->sc_bio.blkdone, sc->sc_dk.dk_label);
1805 1.1 pooka if (sc->retries < EFLASHIORETRIES)
1806 1.1 pooka printf(", retrying");
1807 1.1 pooka printf("\n");
1808 1.1 pooka if (do_perror)
1809 1.1 pooka eflashperror(sc);
1810 1.1 pooka if (sc->retries < EFLASHIORETRIES) {
1811 1.1 pooka sc->retries++;
1812 1.1 pooka callout_reset(&sc->sc_restart_ch, RECOVERYTIME,
1813 1.1 pooka eflashrestart, sc);
1814 1.1 pooka return;
1815 1.1 pooka }
1816 1.1 pooka
1817 1.1 pooka bp->b_error = EIO;
1818 1.1 pooka break;
1819 1.1 pooka case 0:
1820 1.1 pooka if ((sc->sc_bio.flags & ATA_CORR) || sc->retries > 0)
1821 1.1 pooka printf("%s: soft error (corrected)\n",
1822 1.1 pooka device_xname(sc->sc_dev));
1823 1.1 pooka break;
1824 1.1 pooka case ENODEV:
1825 1.1 pooka case E2BIG:
1826 1.1 pooka bp->b_error = EIO;
1827 1.1 pooka break;
1828 1.1 pooka }
1829 1.1 pooka disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid),
1830 1.1 pooka (bp->b_flags & B_READ));
1831 1.1 pooka #if NRND > 0
1832 1.1 pooka rnd_add_uint32(&sc->rnd_source, bp->b_blkno);
1833 1.1 pooka #endif
1834 1.1 pooka biodone(bp);
1835 1.1 pooka sc->openings++;
1836 1.1 pooka eflashstart(sc);
1837 1.1 pooka }
1838 1.1 pooka
1839 1.1 pooka void
1840 1.1 pooka eflashrestart(void *v)
1841 1.1 pooka {
1842 1.1 pooka struct eflash_softc *sc = v;
1843 1.1 pooka struct buf *bp = sc->sc_bp;
1844 1.1 pooka int s;
1845 1.1 pooka DEBUG_PRINT(("%s: eflashrestart\n", device_xname(sc->sc_dev)),
1846 1.1 pooka DEBUG_XFERS);
1847 1.1 pooka
1848 1.1 pooka s = splbio();
1849 1.1 pooka __eflashstart(v, bp);
1850 1.1 pooka splx(s);
1851 1.1 pooka }
1852 1.1 pooka
1853 1.1 pooka int
1854 1.1 pooka eflashread(dev_t dev, struct uio *uio, int flags)
1855 1.1 pooka {
1856 1.1 pooka DEBUG_PRINT(("eflashread\n"), DEBUG_XFERS);
1857 1.1 pooka return (physio(eflashstrategy, NULL, dev, B_READ, minphys, uio));
1858 1.1 pooka }
1859 1.1 pooka
1860 1.1 pooka int
1861 1.1 pooka eflashwrite(dev_t dev, struct uio *uio, int flags)
1862 1.1 pooka {
1863 1.1 pooka DEBUG_PRINT(("eflashwrite\n"), DEBUG_XFERS);
1864 1.1 pooka return (physio(eflashstrategy, NULL, dev, B_WRITE, minphys, uio));
1865 1.1 pooka }
1866 1.1 pooka
1867 1.1 pooka int
1868 1.1 pooka eflashopen(dev_t dev, int flag, int fmt, struct lwp *l)
1869 1.1 pooka {
1870 1.1 pooka struct eflash_softc *sc;
1871 1.1 pooka int part, error;
1872 1.1 pooka
1873 1.2 tsutsui DEBUG_PRINT(("eflashopen %" PRIx64 "\n", dev), DEBUG_FUNCS);
1874 1.1 pooka sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
1875 1.1 pooka if (sc == NULL)
1876 1.1 pooka return (ENXIO);
1877 1.1 pooka
1878 1.1 pooka if (! device_is_active(sc->sc_dev))
1879 1.1 pooka return (ENODEV);
1880 1.1 pooka
1881 1.1 pooka part = EFLASHPART(dev);
1882 1.1 pooka
1883 1.1 pooka mutex_enter(&sc->sc_dk.dk_openlock);
1884 1.1 pooka
1885 1.1 pooka /*
1886 1.1 pooka * If there are wedges, and this is not RAW_PART, then we
1887 1.1 pooka * need to fail.
1888 1.1 pooka */
1889 1.1 pooka if (sc->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
1890 1.1 pooka error = EBUSY;
1891 1.1 pooka goto bad;
1892 1.1 pooka }
1893 1.1 pooka
1894 1.1 pooka if (sc->sc_dk.dk_openmask != 0) {
1895 1.1 pooka /*
1896 1.1 pooka * If any partition is open, but the disk has been invalidated,
1897 1.1 pooka * disallow further opens.
1898 1.1 pooka */
1899 1.1 pooka if ((sc->sc_flags & EFLASHF_LOADED) == 0) {
1900 1.1 pooka error = EIO;
1901 1.1 pooka goto bad;
1902 1.1 pooka }
1903 1.1 pooka } else {
1904 1.1 pooka if ((sc->sc_flags & EFLASHF_LOADED) == 0) {
1905 1.1 pooka sc->sc_flags |= EFLASHF_LOADED;
1906 1.1 pooka
1907 1.1 pooka /* Load the partition info if not already loaded. */
1908 1.1 pooka eflashgetdisklabel(sc);
1909 1.1 pooka }
1910 1.1 pooka }
1911 1.1 pooka
1912 1.1 pooka /* Check that the partition exists. */
1913 1.1 pooka if (part != RAW_PART &&
1914 1.1 pooka (part >= sc->sc_dk.dk_label->d_npartitions ||
1915 1.1 pooka sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
1916 1.1 pooka error = ENXIO;
1917 1.1 pooka goto bad;
1918 1.1 pooka }
1919 1.1 pooka
1920 1.1 pooka /* Insure only one open at a time. */
1921 1.1 pooka switch (fmt) {
1922 1.1 pooka case S_IFCHR:
1923 1.1 pooka sc->sc_dk.dk_copenmask |= (1 << part);
1924 1.1 pooka break;
1925 1.1 pooka case S_IFBLK:
1926 1.1 pooka sc->sc_dk.dk_bopenmask |= (1 << part);
1927 1.1 pooka break;
1928 1.1 pooka }
1929 1.1 pooka sc->sc_dk.dk_openmask =
1930 1.1 pooka sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
1931 1.1 pooka
1932 1.1 pooka mutex_exit(&sc->sc_dk.dk_openlock);
1933 1.1 pooka return 0;
1934 1.1 pooka
1935 1.1 pooka bad:
1936 1.1 pooka mutex_exit(&sc->sc_dk.dk_openlock);
1937 1.1 pooka DEBUG_PRINT(("%s: eflashopen -> %d\n", device_xname(sc->sc_dev), error),
1938 1.1 pooka DEBUG_XFERS);
1939 1.1 pooka return error;
1940 1.1 pooka }
1941 1.1 pooka
1942 1.1 pooka int
1943 1.1 pooka eflashclose(dev_t dev, int flag, int fmt, struct lwp *l)
1944 1.1 pooka {
1945 1.1 pooka struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
1946 1.1 pooka int part = EFLASHPART(dev);
1947 1.1 pooka
1948 1.2 tsutsui DEBUG_PRINT(("eflashclose %" PRIx64 "\n", dev), DEBUG_FUNCS);
1949 1.1 pooka
1950 1.1 pooka mutex_enter(&sc->sc_dk.dk_openlock);
1951 1.1 pooka
1952 1.1 pooka switch (fmt) {
1953 1.1 pooka case S_IFCHR:
1954 1.1 pooka sc->sc_dk.dk_copenmask &= ~(1 << part);
1955 1.1 pooka break;
1956 1.1 pooka case S_IFBLK:
1957 1.1 pooka sc->sc_dk.dk_bopenmask &= ~(1 << part);
1958 1.1 pooka break;
1959 1.1 pooka }
1960 1.1 pooka sc->sc_dk.dk_openmask =
1961 1.1 pooka sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
1962 1.1 pooka
1963 1.1 pooka if (sc->sc_dk.dk_openmask == 0) {
1964 1.1 pooka
1965 1.1 pooka if (! (sc->sc_flags & EFLASHF_KLABEL))
1966 1.1 pooka sc->sc_flags &= ~EFLASHF_LOADED;
1967 1.1 pooka
1968 1.1 pooka DEBUG_PRINT(("%s: eflashclose flg %x\n", device_xname(sc->sc_dev), sc->sc_flags),
1969 1.1 pooka DEBUG_XFERS);
1970 1.1 pooka
1971 1.1 pooka }
1972 1.1 pooka
1973 1.1 pooka mutex_exit(&sc->sc_dk.dk_openlock);
1974 1.1 pooka return 0;
1975 1.1 pooka }
1976 1.1 pooka
1977 1.1 pooka void
1978 1.1 pooka eflashgetdefaultlabel(struct eflash_softc *sc, struct disklabel *lp)
1979 1.1 pooka {
1980 1.1 pooka
1981 1.1 pooka DEBUG_PRINT(("%s: eflashgetdefaultlabel\n", device_xname(sc->sc_dev)), DEBUG_FUNCS);
1982 1.1 pooka memset(lp, 0, sizeof(struct disklabel));
1983 1.1 pooka
1984 1.1 pooka lp->d_secsize = DEV_BSIZE;
1985 1.1 pooka lp->d_ntracks = 1;
1986 1.1 pooka lp->d_nsectors = sc->sc_capacity;
1987 1.1 pooka lp->d_ncylinders = 1;
1988 1.1 pooka lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1989 1.1 pooka
1990 1.1 pooka lp->d_type = DTYPE_ST506; /* ?!? */
1991 1.1 pooka
1992 1.1 pooka strncpy(lp->d_typename, ST506, 16);
1993 1.1 pooka strncpy(lp->d_packname, "fictitious", 16);
1994 1.1 pooka if (sc->sc_capacity > UINT32_MAX)
1995 1.1 pooka lp->d_secperunit = UINT32_MAX;
1996 1.1 pooka else
1997 1.1 pooka lp->d_secperunit = sc->sc_capacity;
1998 1.1 pooka lp->d_rpm = 3600;
1999 1.1 pooka lp->d_interleave = 1;
2000 1.1 pooka lp->d_flags = 0;
2001 1.1 pooka
2002 1.1 pooka lp->d_partitions[RAW_PART].p_offset = 0;
2003 1.1 pooka lp->d_partitions[RAW_PART].p_size =
2004 1.1 pooka lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
2005 1.1 pooka lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
2006 1.1 pooka lp->d_npartitions = RAW_PART + 1;
2007 1.1 pooka
2008 1.1 pooka lp->d_magic = DISKMAGIC;
2009 1.1 pooka lp->d_magic2 = DISKMAGIC;
2010 1.1 pooka lp->d_checksum = dkcksum(lp);
2011 1.1 pooka }
2012 1.1 pooka
2013 1.1 pooka /*
2014 1.1 pooka * Fabricate a default disk label, and try to read the correct one.
2015 1.1 pooka */
2016 1.1 pooka void
2017 1.1 pooka eflashgetdisklabel(struct eflash_softc *sc)
2018 1.1 pooka {
2019 1.1 pooka struct disklabel *lp = sc->sc_dk.dk_label;
2020 1.1 pooka const char *errstring;
2021 1.1 pooka
2022 1.1 pooka DEBUG_PRINT(("%s: eflashgetdisklabel\n", device_xname(sc->sc_dev)), DEBUG_FUNCS);
2023 1.1 pooka
2024 1.1 pooka memset(sc->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
2025 1.1 pooka
2026 1.1 pooka eflashgetdefaultlabel(sc, lp);
2027 1.1 pooka
2028 1.1 pooka #ifdef HAS_BAD144_HANDLING
2029 1.1 pooka sc->sc_bio.badsect[0] = -1;
2030 1.1 pooka #endif
2031 1.1 pooka
2032 1.1 pooka /* BUGBUG: maj==0?? why is this not EFLASHLABELDEV(??sc->sc_dev) */
2033 1.1 pooka errstring = readdisklabel(MAKEEFLASHDEV(0, device_unit(sc->sc_dev),
2034 1.1 pooka RAW_PART), eflashstrategy, lp,
2035 1.1 pooka sc->sc_dk.dk_cpulabel);
2036 1.1 pooka if (errstring) {
2037 1.1 pooka printf("%s: %s\n", device_xname(sc->sc_dev), errstring);
2038 1.1 pooka return;
2039 1.1 pooka }
2040 1.1 pooka
2041 1.1 pooka #if DEBUG
2042 1.1 pooka if (EFLASH_DEBUG(DEBUG_WRITES)) {
2043 1.1 pooka int i, n = sc->sc_dk.dk_label->d_npartitions;
2044 1.1 pooka printf("%s: %d parts\n", device_xname(sc->sc_dev), n);
2045 1.1 pooka for (i = 0; i < n; i++) {
2046 1.1 pooka printf("\t[%d]: t=%x s=%d o=%d\n", i,
2047 1.1 pooka sc->sc_dk.dk_label->d_partitions[i].p_fstype,
2048 1.1 pooka sc->sc_dk.dk_label->d_partitions[i].p_size,
2049 1.1 pooka sc->sc_dk.dk_label->d_partitions[i].p_offset);
2050 1.1 pooka }
2051 1.1 pooka }
2052 1.1 pooka #endif
2053 1.1 pooka
2054 1.1 pooka #ifdef HAS_BAD144_HANDLING
2055 1.1 pooka if ((lp->d_flags & D_BADSECT) != 0)
2056 1.1 pooka bad144intern(sc);
2057 1.1 pooka #endif
2058 1.1 pooka }
2059 1.1 pooka
2060 1.1 pooka void
2061 1.1 pooka eflashperror(const struct eflash_softc *sc)
2062 1.1 pooka {
2063 1.1 pooka const char *devname = device_xname(sc->sc_dev);
2064 1.1 pooka u_int32_t Status = sc->sc_bio.r_error;
2065 1.1 pooka
2066 1.1 pooka printf("%s: (", devname);
2067 1.1 pooka
2068 1.1 pooka if (Status == 0)
2069 1.1 pooka printf("error not notified");
2070 1.1 pooka else
2071 1.1 pooka printf("status=x%x", Status);
2072 1.1 pooka
2073 1.1 pooka printf(")\n");
2074 1.1 pooka }
2075 1.1 pooka
2076 1.1 pooka int
2077 1.1 pooka eflashioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
2078 1.1 pooka {
2079 1.1 pooka struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
2080 1.1 pooka int error = 0, s;
2081 1.1 pooka
2082 1.1 pooka DEBUG_PRINT(("eflashioctl(%lx)\n",xfer), DEBUG_FUNCS);
2083 1.1 pooka
2084 1.1 pooka if ((sc->sc_flags & EFLASHF_LOADED) == 0)
2085 1.1 pooka return EIO;
2086 1.1 pooka
2087 1.1 pooka error = disk_ioctl(&sc->sc_dk, xfer, addr, flag, l);
2088 1.1 pooka if (error != EPASSTHROUGH)
2089 1.1 pooka return (error);
2090 1.1 pooka
2091 1.1 pooka switch (xfer) {
2092 1.1 pooka #ifdef HAS_BAD144_HANDLING
2093 1.1 pooka case DIOCSBAD:
2094 1.1 pooka if ((flag & FWRITE) == 0)
2095 1.1 pooka return EBADF;
2096 1.1 pooka sc->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
2097 1.1 pooka sc->sc_dk.dk_label->d_flags |= D_BADSECT;
2098 1.1 pooka bad144intern(sc);
2099 1.1 pooka return 0;
2100 1.1 pooka #endif
2101 1.1 pooka case DIOCGDINFO:
2102 1.1 pooka *(struct disklabel *)addr = *(sc->sc_dk.dk_label);
2103 1.1 pooka return 0;
2104 1.1 pooka
2105 1.1 pooka case DIOCGPART:
2106 1.1 pooka ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label;
2107 1.1 pooka ((struct partinfo *)addr)->part =
2108 1.1 pooka &sc->sc_dk.dk_label->d_partitions[EFLASHPART(dev)];
2109 1.1 pooka return 0;
2110 1.1 pooka
2111 1.1 pooka case DIOCWDINFO:
2112 1.1 pooka case DIOCSDINFO:
2113 1.1 pooka {
2114 1.1 pooka struct disklabel *lp;
2115 1.1 pooka
2116 1.1 pooka if ((flag & FWRITE) == 0)
2117 1.1 pooka return EBADF;
2118 1.1 pooka
2119 1.1 pooka lp = (struct disklabel *)addr;
2120 1.1 pooka
2121 1.1 pooka mutex_enter(&sc->sc_dk.dk_openlock);
2122 1.1 pooka sc->sc_flags |= EFLASHF_LABELLING;
2123 1.1 pooka
2124 1.1 pooka error = setdisklabel(sc->sc_dk.dk_label,
2125 1.1 pooka lp, /*sc->sc_dk.dk_openmask : */0,
2126 1.1 pooka sc->sc_dk.dk_cpulabel);
2127 1.1 pooka if (error == 0) {
2128 1.1 pooka if (xfer == DIOCWDINFO)
2129 1.1 pooka error = writedisklabel(EFLASHLABELDEV(dev),
2130 1.1 pooka eflashstrategy, sc->sc_dk.dk_label,
2131 1.1 pooka sc->sc_dk.dk_cpulabel);
2132 1.1 pooka }
2133 1.1 pooka
2134 1.1 pooka sc->sc_flags &= ~EFLASHF_LABELLING;
2135 1.1 pooka mutex_exit(&sc->sc_dk.dk_openlock);
2136 1.1 pooka return error;
2137 1.1 pooka }
2138 1.1 pooka
2139 1.1 pooka case DIOCKLABEL:
2140 1.1 pooka if (*(int *)addr)
2141 1.1 pooka sc->sc_flags |= EFLASHF_KLABEL;
2142 1.1 pooka else
2143 1.1 pooka sc->sc_flags &= ~EFLASHF_KLABEL;
2144 1.1 pooka return 0;
2145 1.1 pooka
2146 1.1 pooka case DIOCWLABEL:
2147 1.1 pooka if ((flag & FWRITE) == 0)
2148 1.1 pooka return EBADF;
2149 1.1 pooka if (*(int *)addr)
2150 1.1 pooka sc->sc_flags |= EFLASHF_WLABEL;
2151 1.1 pooka else
2152 1.1 pooka sc->sc_flags &= ~EFLASHF_WLABEL;
2153 1.1 pooka return 0;
2154 1.1 pooka
2155 1.1 pooka case DIOCGDEFLABEL:
2156 1.1 pooka eflashgetdefaultlabel(sc, (struct disklabel *)addr);
2157 1.1 pooka return 0;
2158 1.1 pooka
2159 1.1 pooka case DIOCCACHESYNC:
2160 1.1 pooka return 0;
2161 1.1 pooka
2162 1.1 pooka case DIOCAWEDGE:
2163 1.1 pooka {
2164 1.1 pooka struct dkwedge_info *dkw = (void *) addr;
2165 1.1 pooka
2166 1.1 pooka if ((flag & FWRITE) == 0)
2167 1.1 pooka return (EBADF);
2168 1.1 pooka
2169 1.1 pooka /* If the ioctl happens here, the parent is us. */
2170 1.1 pooka strcpy(dkw->dkw_parent, device_xname(sc->sc_dev));
2171 1.1 pooka return (dkwedge_add(dkw));
2172 1.1 pooka }
2173 1.1 pooka
2174 1.1 pooka case DIOCDWEDGE:
2175 1.1 pooka {
2176 1.1 pooka struct dkwedge_info *dkw = (void *) addr;
2177 1.1 pooka
2178 1.1 pooka if ((flag & FWRITE) == 0)
2179 1.1 pooka return (EBADF);
2180 1.1 pooka
2181 1.1 pooka /* If the ioctl happens here, the parent is us. */
2182 1.1 pooka strcpy(dkw->dkw_parent, device_xname(sc->sc_dev));
2183 1.1 pooka return (dkwedge_del(dkw));
2184 1.1 pooka }
2185 1.1 pooka
2186 1.1 pooka case DIOCLWEDGES:
2187 1.1 pooka {
2188 1.1 pooka struct dkwedge_list *dkwl = (void *) addr;
2189 1.1 pooka
2190 1.1 pooka return (dkwedge_list(&sc->sc_dk, dkwl, l));
2191 1.1 pooka }
2192 1.1 pooka
2193 1.1 pooka case DIOCGSTRATEGY:
2194 1.1 pooka {
2195 1.1 pooka struct disk_strategy *dks = (void *)addr;
2196 1.1 pooka
2197 1.1 pooka s = splbio();
2198 1.1 pooka strlcpy(dks->dks_name, bufq_getstrategyname(sc->sc_q),
2199 1.1 pooka sizeof(dks->dks_name));
2200 1.1 pooka splx(s);
2201 1.1 pooka dks->dks_paramlen = 0;
2202 1.1 pooka
2203 1.1 pooka return 0;
2204 1.1 pooka }
2205 1.1 pooka
2206 1.1 pooka case DIOCSSTRATEGY:
2207 1.1 pooka {
2208 1.1 pooka struct disk_strategy *dks = (void *)addr;
2209 1.1 pooka struct bufq_state *new;
2210 1.1 pooka struct bufq_state *old;
2211 1.1 pooka
2212 1.1 pooka if ((flag & FWRITE) == 0) {
2213 1.1 pooka return EBADF;
2214 1.1 pooka }
2215 1.1 pooka if (dks->dks_param != NULL) {
2216 1.1 pooka return EINVAL;
2217 1.1 pooka }
2218 1.1 pooka dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
2219 1.1 pooka error = bufq_alloc(&new, dks->dks_name,
2220 1.1 pooka BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
2221 1.1 pooka if (error) {
2222 1.1 pooka return error;
2223 1.1 pooka }
2224 1.1 pooka s = splbio();
2225 1.1 pooka old = sc->sc_q;
2226 1.1 pooka bufq_move(new, old);
2227 1.1 pooka sc->sc_q = new;
2228 1.1 pooka splx(s);
2229 1.1 pooka bufq_free(old);
2230 1.1 pooka
2231 1.1 pooka return 0;
2232 1.1 pooka }
2233 1.1 pooka
2234 1.1 pooka default:
2235 1.1 pooka /* NB: we get a DIOCGWEDGEINFO, but nobody else handles it either */
2236 1.1 pooka DEBUG_PRINT(("eflashioctl: unsup x%lx\n", xfer), DEBUG_FUNCS);
2237 1.1 pooka return ENOTTY;
2238 1.1 pooka }
2239 1.1 pooka }
2240 1.1 pooka
2241 1.1 pooka int
2242 1.1 pooka eflashsize(dev_t dev)
2243 1.1 pooka {
2244 1.1 pooka struct eflash_softc *sc;
2245 1.1 pooka int part, omask;
2246 1.1 pooka int size;
2247 1.1 pooka
2248 1.1 pooka DEBUG_PRINT(("eflashsize\n"), DEBUG_FUNCS);
2249 1.1 pooka
2250 1.1 pooka sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
2251 1.1 pooka if (sc == NULL)
2252 1.1 pooka return (-1);
2253 1.1 pooka
2254 1.1 pooka part = EFLASHPART(dev);
2255 1.1 pooka omask = sc->sc_dk.dk_openmask & (1 << part);
2256 1.1 pooka
2257 1.1 pooka if (omask == 0 && eflashopen(dev, 0, S_IFBLK, NULL) != 0)
2258 1.1 pooka return (-1);
2259 1.1 pooka if (sc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
2260 1.1 pooka size = -1;
2261 1.1 pooka else
2262 1.1 pooka size = sc->sc_dk.dk_label->d_partitions[part].p_size *
2263 1.1 pooka (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
2264 1.1 pooka if (omask == 0 && eflashclose(dev, 0, S_IFBLK, NULL) != 0)
2265 1.1 pooka return (-1);
2266 1.1 pooka return (size);
2267 1.1 pooka }
2268 1.1 pooka
2269 1.1 pooka /*
2270 1.1 pooka * Dump core after a system crash.
2271 1.1 pooka */
2272 1.1 pooka int
2273 1.1 pooka eflashdump(dev_t dev, daddr_t blkno, void *va, size_t size)
2274 1.1 pooka {
2275 1.1 pooka /* no we dont */
2276 1.1 pooka return (ENXIO);
2277 1.1 pooka }
2278 1.1 pooka
2279 1.1 pooka #ifdef HAS_BAD144_HANDLING
2280 1.1 pooka /*
2281 1.1 pooka * Internalize the bad sector table.
2282 1.1 pooka */
2283 1.1 pooka void
2284 1.1 pooka bad144intern(struct eflash_softc *sc)
2285 1.1 pooka {
2286 1.1 pooka struct dkbad *bt = &sc->sc_dk.dk_cpulabel->bad;
2287 1.1 pooka struct disklabel *lp = sc->sc_dk.dk_label;
2288 1.1 pooka int i = 0;
2289 1.1 pooka
2290 1.1 pooka DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
2291 1.1 pooka
2292 1.1 pooka for (; i < NBT_BAD; i++) {
2293 1.1 pooka if (bt->bt_bad[i].bt_cyl == 0xffff)
2294 1.1 pooka break;
2295 1.1 pooka sc->sc_bio.badsect[i] =
2296 1.1 pooka bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
2297 1.1 pooka (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
2298 1.1 pooka (bt->bt_bad[i].bt_trksec & 0xff);
2299 1.1 pooka }
2300 1.1 pooka for (; i < NBT_BAD+1; i++)
2301 1.1 pooka sc->sc_bio.badsect[i] = -1;
2302 1.1 pooka }
2303 1.1 pooka #endif
2304 1.1 pooka
2305 1.1 pooka static void
2306 1.1 pooka eflash_params_to_properties(struct eflash_softc *sc)
2307 1.1 pooka {
2308 1.1 pooka prop_dictionary_t disk_info, odisk_info, geom;
2309 1.1 pooka const char *cp;
2310 1.1 pooka
2311 1.1 pooka disk_info = prop_dictionary_create();
2312 1.1 pooka
2313 1.1 pooka cp = ST506;
2314 1.1 pooka
2315 1.1 pooka prop_dictionary_set_cstring_nocopy(disk_info, "type", cp);
2316 1.1 pooka
2317 1.1 pooka geom = prop_dictionary_create();
2318 1.1 pooka
2319 1.1 pooka prop_dictionary_set_uint64(geom, "sectors-per-unit", sc->sc_capacity);
2320 1.1 pooka
2321 1.1 pooka prop_dictionary_set_uint32(geom, "sector-size",
2322 1.1 pooka DEV_BSIZE /* XXX 512? */);
2323 1.1 pooka
2324 1.1 pooka prop_dictionary_set_uint16(geom, "sectors-per-track",
2325 1.1 pooka sc->sc_capacity);
2326 1.1 pooka
2327 1.1 pooka prop_dictionary_set_uint16(geom, "tracks-per-cylinder", 1);
2328 1.1 pooka
2329 1.1 pooka prop_dictionary_set_uint64(geom, "cylinders-per-unit", sc->sc_capacity);
2330 1.1 pooka
2331 1.1 pooka prop_dictionary_set(disk_info, "geometry", geom);
2332 1.1 pooka prop_object_release(geom);
2333 1.1 pooka
2334 1.1 pooka prop_dictionary_set(device_properties(sc->sc_dev),
2335 1.1 pooka "disk-info", disk_info);
2336 1.1 pooka
2337 1.1 pooka /*
2338 1.1 pooka * Don't release disk_info here; we keep a reference to it.
2339 1.1 pooka * disk_detach() will release it when we go away.
2340 1.1 pooka */
2341 1.1 pooka
2342 1.1 pooka odisk_info = sc->sc_dk.dk_info;
2343 1.1 pooka sc->sc_dk.dk_info = disk_info;
2344 1.1 pooka if (odisk_info)
2345 1.1 pooka prop_object_release(odisk_info);
2346 1.1 pooka }
2347 1.1 pooka
2348