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