ace_ebus.c revision 1.1 1 /* $NetBSD: ace_ebus.c,v 1.1 2011/01/26 01:18:50 pooka Exp $ */
2
3 /*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code was written by Alessandro Forin and Neil Pittman
8 * at Microsoft Research and contributed to The NetBSD Foundation
9 * by Microsoft Corporation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: ace_ebus.c,v 1.1 2011/01/26 01:18:50 pooka Exp $");
35
36 #include "rnd.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/conf.h>
42 #include <sys/file.h>
43 #include <sys/stat.h>
44 #include <sys/ioctl.h>
45 #include <sys/buf.h>
46 #include <sys/bufq.h>
47 #include <sys/uio.h>
48 #include <sys/malloc.h>
49 #include <sys/device.h>
50 #include <sys/disklabel.h>
51 #include <sys/disk.h>
52 #include <sys/syslog.h>
53 #include <sys/proc.h>
54 #include <sys/vnode.h>
55 #include <sys/kthread.h>
56 #include <sys/lock.h>
57 #include <sys/queue.h>
58
59 #if NRND > 0
60 #include <sys/rnd.h>
61 #endif
62
63 #include <machine/intr.h>
64 #include <machine/bus.h>
65
66 #include "locators.h"
67 #include <prop/proplib.h>
68
69 #include <emips/ebus/ebusvar.h>
70 #include <emips/emips/machdep.h>
71 #include <machine/emipsreg.h>
72
73 /* Structure returned by the Identify command (see CFlash specs)
74 * NB: We only care for the first sector so that is what we define here.
75 * NB: Beware of mis-alignment for all 32bit things
76 */
77 typedef struct _CFLASH_IDENTIFY {
78 uint16_t Signature; /* Word 0 */
79 #define CFLASH_SIGNATURE 0x848a
80 uint16_t DefaultNumberOfCylinders; /* Word 1 */
81 uint16_t Reserved1; /* Word 2 */
82 uint16_t DefaultNumberOfHeads; /* Word 3 */
83 uint16_t Obsolete1[2]; /* Word 4 */
84 uint16_t DefaultSectorsPerTrack; /* Word 6 */
85 uint16_t SectorsPerCard[2]; /* Word 7 */
86 uint16_t Obsolete2; /* Word 9 */
87 uint8_t SerialNumber[20]; /* padded, right-justified Word 10 */
88 uint16_t Obsolete3[2]; /* Word 20 */
89 uint16_t EccBytesInRWLong; /* Word 22 */
90 uint8_t FirmwareRevision[8]; /* Word 23 */
91 uint8_t ModelNumber[40]; /* Word 27 */
92 uint16_t SectorsInRWMultiple; /* Word 47 */
93 uint16_t Reserved2; /* Word 48 */
94 uint16_t Capabilities; /* Word 49 */
95 uint16_t Reserved3; /* Word 50 */
96 uint16_t PioMode; /* Word 51 */
97 uint16_t Obsolete4; /* Word 52 */
98 uint16_t FieldValidity; /* Word 53 */
99 uint16_t CurrentNumberOfCylinders; /* Word 54 */
100 uint16_t CurrentNumberOfHeads; /* Word 55 */
101 uint16_t CurrentSectorsPerTrack; /* Word 56 */
102 uint16_t CurrentCapacity[2]; /* Word 57 */
103 uint16_t MultiSectorSettings; /* Word 59 */
104 uint16_t NumberOfAddressableSectors[2]; /* Word 60 */
105 uint16_t Reserved4; /* Word 62 */
106 uint16_t MultiWordDmaTransfer; /* Word 63 */
107 uint16_t AdvancedPioModes; /* Word 64 */
108 uint16_t MinimumMultiWordDmaTiming; /* Word 65 */
109 uint16_t RecommendedMultiWordDmaTiming; /* Word 66 */
110 uint16_t PioTimingNoFlowControl; /* Word 67 */
111 uint16_t PioTimingWithFlowControl; /* Word 68 */
112 uint16_t Reserved5[13]; /* Word 69 */
113 uint16_t FeaturesSupported[3]; /* Word 82 */
114 uint16_t FeaturesEnabled[3]; /* Word 85 */
115 uint16_t UdmaMode; /* Word 88 */
116 uint16_t SecurityEraseTime; /* Word 89 */
117 uint16_t EnhancedSecurityEraseTime; /* Word 90 */
118 uint16_t CurrentPowerManagementValue; /* Word 91 */
119 uint8_t Reserved6[72]; /* Word 92-127 */
120 uint8_t SecondHalf[256]; /* Word 128-255 */
121 } CFLASH_IDENTIFY, *PCFLASH_IDENTIFY;
122
123 #define SIZEOF_IDENTIFY CF_SECTOR_SIZE /* must be a sector multiple */
124
125 /* Instead of dragging in atavar.h.. */
126 /*
127 * Parameters/state needed by the controller to perform an ATA bio.
128 */
129 struct ace_bio {
130 volatile int flags;/* cmd flags */
131 #define ATA_POLL 0x0002 /* poll for completion */
132 #define ATA_SINGLE 0x0008 /* transfer must be done in singlesector mode */
133 #define ATA_READ 0x0020 /* transfer is a read (otherwise a write) */
134 #define ATA_CORR 0x0040 /* transfer had a corrected error */
135 daddr_t blkno; /* block addr */
136 daddr_t blkdone;/* number of blks transferred */
137 size_t nblks; /* number of blocks currently transferring */
138 size_t nbytes; /* number of bytes currently transferring */
139 char *databuf;/* data buffer address */
140 volatile int error;
141 #define NOERROR 0 /* There was no error (r_error invalid), else see acedone()*/
142 #define FAILED(er) (er != 0)
143 #define EDOOFUS EIO
144
145 u_int32_t r_error;/* copy of status register */
146 #ifdef HAS_BAD144_HANDLING
147 daddr_t badsect[127];/* 126 plus trailing -1 marker */
148 #endif
149 };
150 /* End of atavar.h*/
151
152 struct ace_softc {
153 /* General disk infos */
154 device_t sc_dev;
155
156 struct disk sc_dk;
157 struct bufq_state *sc_q;
158 struct callout sc_restart_ch;
159
160 /* IDE disk soft states */
161 struct buf *sc_bp; /* buf being transfered */
162 struct buf *active_xfer; /* buf handoff to thread */
163 /* current transfer data */
164 struct ace_bio sc_bio; /* current transfer */
165
166 struct proc *ch_thread;
167 int ch_flags;
168 #define ATACH_SHUTDOWN 0x02 /* thread is shutting down */
169 #define ATACH_IRQ_WAIT 0x10 /* thread is waiting for irq */
170 #define ATACH_DISABLED 0x80 /* channel is disabled */
171 #define ATACH_TH_RUN 0x100 /* the kernel thread is working */
172 #define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */
173
174 int openings;
175 int media_has_changed;
176 #define ACECE_MC 0x20 /* media changed */
177 #define ACECE_MCR 0x08 /* media change requested */
178 struct _CFLASH_IDENTIFY sc_params;/* drive characteristics found */
179
180 int sc_flags;
181 #define ACEF_WLABEL 0x004 /* label is writable */
182 #define ACEF_LABELLING 0x008 /* writing label */
183 #define ACEF_LOADED 0x010 /* parameters loaded */
184 #define ACEF_WAIT 0x020 /* waiting for resources */
185 #define ACEF_KLABEL 0x080 /* retain label after 'full' close */
186
187 u_int64_t sc_capacity;
188 uint32_t sc_multi; /* max sectors per xfer */
189
190 struct _Sac *sc_dr; /* reg pointers */
191 int hw_busy;
192 int retries; /* number of xfer retry */
193
194 #if NRND > 0
195 rndsource_element_t rnd_source;
196 #endif
197 };
198
199 int ace_ebus_match(struct device *, struct cfdata *, void *);
200 void ace_ebus_attach(struct device *, struct device *, void *);
201 void aceattach(struct ace_softc *);
202 int acedetach(struct device *, int);
203 int aceactivate(struct device *, enum devact);
204
205 void acedone(struct ace_softc *);
206 static void ace_params_to_properties(struct ace_softc *ace);
207
208 CFATTACH_DECL_NEW(ace_ebus, sizeof(struct ace_softc),
209 ace_ebus_match, ace_ebus_attach, acedetach, aceactivate);
210
211 int ace_ebus_intr(void *cookie, void *f);
212
213 static void sysace_thread(void *arg);
214
215 int
216 ace_ebus_match(struct device *parent, struct cfdata *match, void *aux)
217 {
218 struct ebus_attach_args *d = aux;
219 struct _Sac *sac = (struct _Sac *)d->ia_vaddr;
220
221 if (strcmp("ace", d->ia_name) != 0)
222 return (0);
223 if ((sac == NULL) ||
224 ((sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE))
225 return 0;
226 return (1);
227 }
228
229 void
230 ace_ebus_attach(struct device *parent, struct device *self, void *aux)
231 {
232 struct ace_softc *ace = device_private(self);
233 struct ebus_attach_args *ia = aux;
234 int error;
235
236 /*
237 * It's on the baseboard, with a dedicated interrupt line.
238 */
239 ace->sc_dr = (struct _Sac *)ia->ia_vaddr;
240 ace->sc_dev = self;
241 #if DEBUG
242 printf(" virt=%p", (void*)ace->sc_dr);
243 #endif
244 printf(" : System ACE\n");
245
246 ebus_intr_establish(parent, (void*)ia->ia_cookie, IPL_BIO,
247 ace_ebus_intr, ace);
248
249 config_pending_incr();
250
251 error = kthread_create(PRI_NONE, 0, NULL, sysace_thread,
252 ace, NULL, "%s", device_xname(ace->sc_dev));
253 if (error)
254 aprint_error_dev(ace->sc_dev, "unable to create kernel "
255 "thread: error %d\n", error);
256 }
257
258 /* Sysace driver I(af) wrote for FreeBsd.
259 */
260 #define CF_SECBITS 9
261 #define CF_SECTOR_SIZE (1 << CF_SECBITS)
262
263 static int sysace_attach(struct ace_softc *sc);
264 static int sysace_reset(struct ace_softc *sc);
265 static int sysace_identify(struct ace_softc *sc);
266 static int sysace_lock_registers(struct ace_softc *sc);
267 static int sysace_unlock_registers(struct ace_softc *sc);
268 static int sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba, uint32_t nSectors);
269 static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize);
270 static int sysace_read_at (struct ace_softc *sc, daddr_t start_sector, char *buffer,
271 size_t nblocks, size_t * pSizeRead);
272 static int sysace_write_at(struct ace_softc *sc, daddr_t start_sector, char *buffer,
273 size_t nblocks, size_t * pSizeWritten);
274 #ifdef USE_ACE_FOR_RECONFIG /* Old code, despised and replaced by ICAP */
275 static int sysace_send_config(struct ace_softc *sc,
276 uint32_t *Data, unsigned int nBytes);
277 #endif
278
279 #define DEBUG_INTR 0x01
280 #define DEBUG_XFERS 0x02
281 #define DEBUG_STATUS 0x04
282 #define DEBUG_FUNCS 0x08
283 #define DEBUG_PROBE 0x10
284 #define DEBUG_WRITES 0x20
285 #define DEBUG_READS 0x40
286 #define DEBUG_ERRORS 0x80
287 #ifdef DEBUG
288 int ace_debug = DEBUG_ERRORS;//|DEBUG_WRITES;
289 #define ACE_DEBUG(x) (ace_debug & (x))
290 #define DBGME(_lev_,_x_) if ((_lev_) & ace_debug) _x_
291 #else
292 #define ACE_DEBUG(x) (0)
293 #define DBGME(_lev_,_x_)
294 #endif
295 #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_)
296
297 static int
298 sysace_attach(struct ace_softc *sc)
299 {
300 int error;
301
302 DBGME(DEBUG_FUNCS,printf("Sysace::delayed_attach %p\n", sc));
303
304 sc->media_has_changed = TRUE;
305 sc->sc_capacity = 0;
306
307 error = sysace_reset(sc);
308 if (error) {
309 device_printf(sc->sc_dev,"failed to reset, errno=%d\n", error);
310 goto Out;
311 }
312
313 error = sysace_identify(sc);
314 if (error) {
315 device_printf(sc->sc_dev,"failed to identify card, errno=%d.\n", error);
316 goto Out;
317 }
318
319 DBGME(DEBUG_PROBE,device_printf(sc->sc_dev,"Card has %qx sectors.\n", sc->sc_capacity));
320 if (sc->sc_capacity == 0) {
321 device_printf(sc->sc_dev,"size 0, no card? Wont work.\n");
322 error = EDOOFUS;
323 goto Out;
324 }
325
326 sc->media_has_changed = FALSE;
327 Out:
328 return error;
329 }
330
331 static void
332 sysace_wedges(void *arg);
333 extern int dkwedge_autodiscover;
334
335 /* Aux temp thread to avoid deadlock when doing the partitio.. ahem wedges thing.
336 */
337 static void
338 sysace_wedges(void *arg)
339 {
340 struct ace_softc *sc = (struct ace_softc*)arg;
341
342 DBGME(DEBUG_STATUS,printf("Sysace::wedges started for %p\n", sc));
343
344 /* Discover wedges on this disk. */
345 dkwedge_autodiscover = 1;
346 dkwedge_discover(&sc->sc_dk);
347
348 config_pending_decr();
349
350 DBGME(DEBUG_STATUS,printf("Sysace::thread done for %p\n", sc));
351 kthread_exit(0);
352 }
353
354 static void
355 sysace_thread(void *arg)
356 {
357 struct ace_softc *sc = (struct ace_softc*)arg;
358 struct buf *bp;
359 int s, error;
360
361 DBGME(DEBUG_STATUS,printf("Sysace::thread started for %p\n", sc));
362
363 s = splbio();
364 aceattach(sc);
365 splx(s);
366
367 error = kthread_create(PRI_NONE, 0 /* MPSAFE??? */, NULL,
368 sysace_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev));
369 if (error)
370 aprint_error_dev(sc->sc_dev, "wedges: unable to create "
371 "kernel thread: error %d\n", error);
372
373 DBGME(DEBUG_STATUS,printf("Sysace::thread service active for %p\n", sc));
374
375 s = splbio();
376 for (;;) {
377 /* Get next I/O request, wait if necessary
378 */
379 if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 &&
380 (sc->active_xfer == NULL)) {
381 sc->ch_flags &= ~ATACH_TH_RUN;
382 (void) tsleep(&sc->ch_thread, PRIBIO, "aceth", 0);
383 sc->ch_flags |= ATACH_TH_RUN;
384 }
385 if (sc->ch_flags & ATACH_SHUTDOWN) {
386 break;
387 }
388 bp = sc->active_xfer;
389 sc->active_xfer = NULL;
390 if (bp != NULL) {
391
392 size_t sz, bnow;
393
394 DBGME(DEBUG_XFERS,printf("Sysace::task %p %p %x %p %qx %d (%zd)\n", sc, bp,
395 sc->sc_bio.flags, sc->sc_bio.databuf, sc->sc_bio.blkno,
396 sc->sc_bio.nbytes, sc->sc_bio.nblks));
397
398 sc->sc_bio.error = 0;
399 for (; sc->sc_bio.nblks > 0;) {
400
401 bnow = sc->sc_bio.nblks;
402 if (sc->sc_bio.flags & ATA_SINGLE) bnow = 1;
403
404 if (sc->sc_bio.flags & ATA_READ) {
405 sc->sc_bio.error =
406 sysace_read_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
407 } else {
408 sc->sc_bio.error =
409 sysace_write_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
410 }
411
412 if (FAILED(sc->sc_bio.error))
413 break;
414
415 sc->sc_bio.blkno += sz; /* in blocks */
416 sc->sc_bio.nblks -= sz;
417 sc->sc_bio.blkdone += sz;
418 sz = sz << CF_SECBITS; /* in bytes */
419 sc->sc_bio.databuf += sz;
420 sc->sc_bio.nbytes -= sz;
421 }
422
423 acedone(sc);
424 }
425 }
426
427 splx(s);
428 sc->ch_thread = NULL;
429 wakeup(&sc->ch_flags);
430 kthread_exit(0);
431 }
432
433 /* Worker routines
434 */
435 #if _DEBUG
436 typedef char *NAME;
437 typedef struct _REGDESC {
438 NAME RegisterName;
439 NAME BitNames[32];
440 } REGDESC, *PREGDESC;
441
442 static void SysacePrintRegister(const REGDESC *Desc, uint32_t Value)
443 {
444 int i;
445 printf("\t%s %x =", Desc->RegisterName, Value);
446 for (i = 31; i >= 0; i--) {
447 if (Value & (1 << i))
448 printf(" %s",
449 (Desc->BitNames[i]) ? Desc->BitNames[i] : "?");
450 }
451 printf("\n");
452 }
453
454 static uint32_t SysaceDumpRegisters(struct _Sac *regs)
455 {
456 const REGDESC Control_Names =
457 { "Control",
458 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
459 "RST", // 0x00010000
460 "BUS8", // 0x00020000
461 "BUS16", // 0x00040000
462 "BUS32", // 0x00080000
463 "IRQ", // 0x00100000
464 "BRDY", // 0x00200000
465 "IMSK0", // 0x00400000
466 "IMSK1", // 0x00800000
467 "TD0", // 0x0f000000
468 "TD1", // 0x0f000000
469 "TD2", // 0x0f000000
470 "TD3", // 0x0f000000
471 "BUFW8", // 0x10000000
472 "BUFW16", // 0x20000000
473 "BUFW32", // 0x40000000
474 "DEBUG"} // 0x80000000
475 };
476
477 const REGDESC STATUS_Names =
478 { "STATUS",
479 {"CFGLOCK", // 0x00000001
480 "MPULOCK", // 0x00000002
481 "CFGERROR", // 0x00000004
482 "CFCERROR", // 0x00000008
483 "CFDETECT", // 0x00000010
484 "DATABUFRDY", // 0x00000020
485 "DATABUFWRITE", //0x00000040
486 "CFGDONE", // 0x00000080
487 "RDYFORCFCMD", // 0x00000100
488 "CFGMODEPIN", // 0x00000200
489 0,0,0,
490 "CFGADDRPIN0", // 0x0000e000
491 "CFGADDRPIN1", // 0x0000e000
492 "CFGADDRPIN2", // 0x0000e000
493 0,
494 "CFBSY", // 0x00020000
495 "CFRDY", // 0x00040000
496 "CFDWF", // 0x00080000
497 "CFDSC", // 0x00100000
498 "CFDRQ", // 0x00200000
499 "CFCORR", // 0x00400000
500 "CFERR", // 0x00800000
501 0,}
502 };
503
504 const REGDESC ERRORREG_Names =
505 { "ERRORREG",
506 {"CARDRESETERR", // 0x00000001
507 "CARDRDYERR", // 0x00000002
508 "CARDREADERR", // 0x00000004
509 "CARDWRITEERR", // 0x00000008
510 "SECTORRDYERR", // 0x00000010
511 "CFGADDRERR", // 0x00000020
512 "CFGFAILED", // 0x00000040
513 "CFGREADERR", // 0x00000080
514 "CFGINSTRERR", // 0x00000100
515 "CFGINITERR", // 0x00000200
516 0,
517 "CFBBK", // 0x00000800
518 "CFUNC", // 0x00001000
519 "CFIDNF", // 0x00002000
520 "CFABORT", // 0x00004000
521 "CFAMNF", // 0x00008000
522 0,}
523 };
524
525 const NAME CommandNames[8] =
526 { "0", // 0x0000
527 "RESETMEMCARD", // 0x0100
528 "IDENTIFYMEMCARD", // 0x0200
529 "READMEMCARDDATA", // 0x0300
530 "WRITEMEMCARDDATA", // 0x0400
531 "5", // 0x0500
532 "ABORT", // 0x0600
533 "7" // 0x0700
534 };
535
536 const REGDESC CONTROLREG_Names =
537 { "CONTROLREG",
538 {"FORCELOCKREQ", // 0x00000001
539 "LOCKREQ", // 0x00000002
540 "FORCECFGADDR", // 0x00000004
541 "FORCECFGMODE", // 0x00000008
542 "CFGMODE", // 0x00000010
543 "CFGSTART", // 0x00000020
544 "CFGSEL_MPU", // 0x00000040
545 "CFGRESET", // 0x00000080
546 "DATABUFRDYIRQ", // 0x00000100
547 "ERRORIRQ", // 0x00000200
548 "CFGDONEIRQ", // 0x00000400
549 "RESETIRQ", // 0x00000800
550 "CFGPROG", // 0x00001000
551 "CFGADDR_B0", // 0x00002000
552 "CFGADDR_B1", // 0x00004000
553 "CFGADDR_B2", // 0x00008000
554 0,}
555 };
556
557 const REGDESC FATSTATREG_Names =
558 { "FATSTATREG",
559 {"MBRVALID", // 0x00000001
560 "PBRVALID", // 0x00000002
561 "MBRFAT12", // 0x00000004
562 "PBRFAT12", // 0x00000008
563 "MBRFAT16", // 0x00000010
564 "PBRFAT16", // 0x00000020
565 "CALCFAT12", // 0x00000040
566 "CALCFAT16", // 0x00000080
567 0, }
568 };
569
570 printf("Sysace@%p:\n", regs);
571 printf("\tTag %x\n", regs->Tag);
572 SysacePrintRegister(&Control_Names, regs->Control);
573 printf("\tBUSMODEREG %x\n", regs->BUSMODEREG);
574 SysacePrintRegister(&STATUS_Names, regs->STATUS);
575 SysacePrintRegister(&ERRORREG_Names, regs->ERRORREG);
576 printf("\tCFGLBAREG %x\n", regs->CFGLBAREG);
577 printf("\tMPULBAREG %x\n", regs->MPULBAREG);
578 printf("\tVERSIONREG %x\n", regs->VERSIONREG);
579 printf("\tSECCNTCMDREG %x = %s cnt=%d\n", regs->SECCNTCMDREG,
580 CommandNames[(regs->SECCNTCMDREG >> 8)&7],
581 regs->SECCNTCMDREG & SAC_SECCCNT);
582 SysacePrintRegister(&CONTROLREG_Names, regs->CONTROLREG);
583 SysacePrintRegister(&FATSTATREG_Names, regs->FATSTATREG);
584
585 return 1;
586 }
587
588 #else
589 #define SysaceDumpRegisters(_c_)
590 #endif
591
592 /* Reset the device and the interface
593 */
594 static int sysace_reset(struct ace_softc *sc)
595 {
596 struct _Sac *regs = sc->sc_dr;
597
598 DBGME(DEBUG_FUNCS,printf("Sysace::Reset %p\n", sc));
599
600 /* 16bit etc etc */
601 uint32_t BusMode, Control;
602
603 /* reset our interface */
604 regs->Control = SAC_RST;
605 DELAY(200);
606
607 /* repeat on both byte lanes */
608 regs->BUSMODEREG = SAC_MODE16 | (SAC_MODE16 << 8);
609 DELAY(1);
610
611 /* check what our interface does and what the SysACE expects */
612 Control = regs->Control;
613 BusMode = regs->BUSMODEREG;
614
615 /* get them to agree */
616 if (BusMode & SAC_MODE16)
617 {
618 regs->Control = Control | SAC_BUS16;
619 regs->Control = regs->Control & ~SAC_BUS8;
620 }
621 else
622 {
623 regs->Control = Control | SAC_BUS8;
624 regs->Control = regs->Control & ~SAC_BUS16;
625 }
626
627 /* check that it worked */
628 BusMode = regs->BUSMODEREG;
629 Control = regs->Control;
630
631 if (((BusMode & SAC_MODE16) == 0) && ((Control & SAC_BUS8) == 0)) return EDOOFUS;
632 if (((BusMode & SAC_MODE16) > 0) && ((Control & SAC_BUS16) == 0)) return EDOOFUS;
633
634 /* interrupts off for now */
635 regs->Control &= ~SAC_INTMASK;
636 #define SAC_INTERRUPTS (SAC_DATABUFRDYIRQ | SAC_ERRORIRQ )// | SAC_CFGDONEIRQ)
637 Control = regs->CONTROLREG;
638 Control = (Control & ~SAC_INTERRUPTS) | SAC_RESETIRQ | SAC_FORCECFGMODE;
639 regs->CONTROLREG = Control;
640 regs->CONTROLREG = Control & ~SAC_RESETIRQ;
641
642 /* no command */
643 regs->MPULBAREG = 0;
644
645 return 0;
646 }
647
648 /* Take control of the ACE datapath
649 */
650 static int sysace_lock_registers(struct ace_softc *sc)
651 {
652 uint32_t Status;
653 int i;
654
655 DBGME(DEBUG_FUNCS,printf("Sysace::Lock %p\n", sc));
656
657 /* Locked already?
658 */
659 Status = sc->sc_dr->STATUS;
660 if (Status & SAC_MPULOCK)
661 return TRUE;
662
663 /* Request lock
664 */
665 sc->sc_dr->CONTROLREG |= SAC_LOCKREQ;
666
667 /* Spin a bit until we get it
668 */
669 for (i = 0; i < 200; i++) {
670 Status = sc->sc_dr->STATUS;
671 if (Status & SAC_MPULOCK)
672 return TRUE;
673 DELAY(100);
674 DBGME(DEBUG_FUNCS,printf("Sysace::Lock loops.. (st=%x)\n",Status));
675 }
676
677 /* oopsie!
678 */
679 DBGME(DEBUG_ERRORS,printf("Sysace::Lock timeout (st=%x)\n",Status));
680 SysaceDumpRegisters(sc->sc_dr);
681 return FALSE;
682 }
683
684 /* Release control of the ACE datapath
685 */
686 static int sysace_unlock_registers(struct ace_softc *sc)
687 {
688 uint32_t Status;
689 int i;
690
691 DBGME(DEBUG_FUNCS,printf("Sysace::Unlock %p\n", sc));
692
693 /* Clear reset
694 */
695 sc->sc_dr->CONTROLREG &= ~SAC_CFGRESET;
696
697 /* Unlocked already?
698 */
699 Status = sc->sc_dr->STATUS;
700 if (0 == (Status & SAC_MPULOCK))
701 return TRUE;
702
703 /* Request unlock
704 */
705 sc->sc_dr->CONTROLREG &= ~SAC_LOCKREQ;
706
707 /* Spin a bit until we get it
708 */
709 for (i = 0; i < 200; i++) {
710 Status = sc->sc_dr->STATUS;
711 if (0 == (Status & SAC_MPULOCK))
712 return TRUE;
713 DELAY(100);
714 DBGME(DEBUG_FUNCS,printf("Sysace::Unlock loops.. (st=%x)\n",Status));
715 }
716
717 /* oopsie!
718 */
719 DBGME(DEBUG_ERRORS,printf("Sysace::Unlock timeout (st=%x)\n",Status));
720 SysaceDumpRegisters(sc->sc_dr);
721 return FALSE;
722 }
723
724 /* Check if the ACE is waiting for a comamnd
725 */
726 #define sysace_ready(_s_) ((_s_)->sc_dr->STATUS & SAC_RDYFORCFCMD)
727
728 /* Check if the ACE is executing a comamnd
729 */
730 #define sysace_busy(_s_) ((_s_)->sc_dr->STATUS & SAC_CFBSY)
731
732 /* Turn on interrupts from the ACE
733 */
734 #define sysace_inton(_s_) { \
735 (_s_)->sc_dr->CONTROLREG |= SAC_INTERRUPTS; \
736 (_s_)->sc_dr->Control |= SAC_INTMASK; \
737 }
738
739 /* Turn off interrupts from the ACE
740 */
741 #define sysace_intoff(_s_) { \
742 (_s_)->sc_dr->CONTROLREG &= ~SAC_INTERRUPTS; \
743 (_s_)->sc_dr->Control &= ~SAC_INTMASK; \
744 }
745
746 /* Start a command on the ACE, such as read or identify.
747 */
748 static int sysace_start(struct ace_softc *sc,
749 uint32_t Command,
750 uint32_t Lba,
751 uint32_t nSectors)
752 {
753 /* Lock it if not already
754 */
755 if (!sysace_lock_registers(sc)) {
756 /* printed already */
757 return ETIMEDOUT;
758 }
759
760 /* Is there a CF inserted
761 */
762 if (! (sc->sc_dr->STATUS & SAC_CFDETECT)) {
763 /* NB: Not a failure state */
764 DBGME(DEBUG_ERRORS,printf("Sysace:: no media (st=%x)\n",sc->sc_dr->STATUS));
765 if (sc->sc_capacity) {
766 sc->media_has_changed = TRUE;
767 sc->sc_capacity = 0;
768 }
769 return ENODEV;
770 }
771
772 /* Is it ready for a command
773 */
774 if (!sysace_ready(sc)) {
775 DBGME(DEBUG_ERRORS,printf("Sysace:: not ready (st=%x)\n",sc->sc_dr->STATUS));
776 SysaceDumpRegisters(sc->sc_dr);
777 return EBUSY;
778 }
779
780 /* sector number and command
781 */
782 sc->sc_dr->MPULBAREG = Lba;
783 sc->sc_dr->SECCNTCMDREG = (uint16_t)(Command | (nSectors & SAC_SECCCNT));
784
785 /* re-route the chip
786 * NB: The "RESET" is actually not much of a misnomer.
787 * The chip was designed for a one-shot execution at reset time,
788 * namely loading the configuration data into the FPGA. So.
789 */
790 sc->hw_busy = TRUE;
791 sc->sc_dr->CONTROLREG |= SAC_CFGRESET;
792 return 0;
793 }
794
795 /* Identify the (size of the) CompactFlash card inserted in the slot.
796 */
797 static int sysace_identify(struct ace_softc *sc)
798 {
799 PCFLASH_IDENTIFY Identify = &sc->sc_params;
800 uint32_t Status = 0;
801 int i, j, error;
802
803 DBGME(DEBUG_FUNCS,printf("Sysace::Identify %p\n", sc));
804
805 /* Turn on interrupts before we start the command
806 */
807 sysace_inton(sc); /* BUGBUG we should add polling mode (for dump too) */
808
809 /* This will invalidate the ACE's current sector data
810 */
811 sc->sc_capacity = 0;
812
813 /* Get it going
814 */
815 error = sysace_start(sc,
816 SAC_CMD_IDENTIFYMEMCARD,
817 0,
818 1);
819
820 /* Wait until its done
821 */
822 if (!FAILED(error)) {
823
824 /* Might be called during autoconf, no interrupts */
825 if (cold) {
826 do {
827 DELAY(10);
828 Status = sc->sc_dr->STATUS;
829 } while (0 == (Status & (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)));
830 } else {
831 while (sc->hw_busy) {
832 DBGME(DEBUG_FUNCS,printf("Sysace:: cwait.. (st=%x) sizeof=%d\n",sc->sc_dr->STATUS, sizeof(*Identify)));
833 error = tsleep(&sc->media_has_changed, PRIBIO, "aceidfy", 0);
834 }
835 }
836
837 /* Did it work?
838 */
839 Status = sc->sc_dr->STATUS;
840
841 if (Status & SAC_DATABUFRDY) {
842
843 /* Yes, pull out all the data.
844 * NB: Until we do so the chip will not be ready for another command
845 */
846 for (i = 0; i < sizeof(*Identify); i += 4) {
847
848 /* Verify the (32-bytes) FIFO has reloaded
849 */
850 for (j = 0; j < 10; j++) {
851 Status = sc->sc_dr->STATUS;
852 if (Status & SAC_DATABUFRDY)
853 break;
854 DELAY(10);
855 }
856 if (Status & SAC_DATABUFRDY)
857 {
858 uint32_t Data32;
859
860 /* This pulls two 16-bit words out of the FIFO.
861 * They are ordered in LE.
862 * NB: Yes this is different from regular data accesses
863 */
864 Data32 = sc->sc_dr->DATABUFREG[0];
865 #if _BYTE_ORDER == _LITTLE_ENDIAN
866 /* all is fine */
867 #else
868 Data32 = (Data32 >> 16) | (Data32 << 16);
869 #endif
870 memcpy(((char*)Identify)+i,&Data32,4);
871 }
872 else
873 /* Ooops, what's going on here?
874 */
875 {
876 DBGME(DEBUG_ERRORS,printf("Sysace::!DATABUFRDY %x\n",Status));
877 error = EIO;
878 break;
879 }
880 }
881
882 /* Make sure we did ok and pick up the relevant info
883 */
884 if (Status & SAC_DATABUFRDY)
885 {
886 DBGME(DEBUG_XFERS,device_printf(sc->sc_dev,"model: %.40s/%.20s\n",
887 Identify->ModelNumber, Identify->SerialNumber));
888 if (Identify->Signature == CFLASH_SIGNATURE)
889 {
890 DBGME(DEBUG_PROBE,printf("Sysace::Card is %.40s::%.20s\n",
891 Identify->ModelNumber, Identify->SerialNumber));
892
893 sc->sc_capacity =
894 (Identify->SectorsPerCard[0] << 16) | Identify->SectorsPerCard[1];
895 DBGME(DEBUG_PROBE,printf("Sysace::sc_capacity x%qx\n", sc->sc_capacity));
896 ace_params_to_properties(sc);
897 } else {
898 DBGME(DEBUG_ERRORS,printf("Sysace::Bad card signature? %x != %x\n",
899 Identify->Signature, CFLASH_SIGNATURE));
900 sc->sc_capacity = 0;
901 error = ENXIO;
902 }
903 }
904 else
905 {
906 error = ETIMEDOUT;
907 }
908 }
909 else
910 /* No, it did not work. Maybe there is no card inserted
911 */
912 {
913 DBGME(DEBUG_ERRORS,printf("Sysace::Identify failed, missing CFLASH card?\n"));
914 SysaceDumpRegisters(sc->sc_dr);
915 /* BUGBUG Fix the error code accordingly */
916 error = ETIMEDOUT;
917 }
918 }
919
920 /* remember this jic */
921 sc->sc_bio.r_error = Status;
922
923 /* Free the ACE for the JTAG, just in case */
924 sysace_unlock_registers(sc);
925
926 /* Done
927 */
928 return error;
929 }
930
931 /* Common code for read&write argument validation
932 */
933 static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize)
934 {
935 daddr_t Size;
936
937 /* Verify that we know the media size
938 */
939 if (sc->sc_capacity == 0) {
940 int error = sysace_identify(sc);
941 if (FAILED(error))
942 return error;
943 }
944
945 /* Validate args
946 */
947 if (start >= sc->sc_capacity) {
948 *pSize = 0;
949 DBGME(DEBUG_ERRORS,printf("Sysace::ValidateArg(%qx) EOF\n", start));
950 return E2BIG;
951 }
952
953 /* Adjust size if necessary
954 */
955 Size = start + *pSize;
956 if (Size > sc->sc_capacity) {
957 /* At most this many sectors
958 */
959 Size = sc->sc_capacity - start;
960 *pSize = (size_t)Size;
961 }
962
963 DBGME(DEBUG_FUNCS,printf("Sysace::Validate %qx %zd\n", start,*pSize));
964 return 0;
965 }
966
967 /* Read SIZE bytes from sysace device, at offset Position
968 */
969 uint32_t ace_maxatatime = 255;
970 #define MAXATATIME ace_maxatatime //255 /* BUGBUG test me on real hardware!! */
971
972 static int sysace_read_at (struct ace_softc *sc,
973 daddr_t start_sector, char *buffer, size_t nblocks,
974 size_t * pSizeRead)
975 {
976 int error;
977 uint32_t BlocksThisTime;
978 uint32_t Status = 0, SizeRead = 0;
979 uint32_t i, j;
980
981 DBGME(DEBUG_XFERS|DEBUG_READS,printf("SysaceReadAt(%p %qx %p %zd %p)\n",
982 sc, start_sector, buffer, nblocks, pSizeRead));
983
984 /* Validate & trim arguments
985 */
986 error = sysace_validate(sc, start_sector, &nblocks);
987
988 /* Repeat until we are done or error
989 */
990 while (error == 0) {
991
992 /* .. one bunch of sectors at a time
993 */
994 BlocksThisTime = nblocks;
995 if (BlocksThisTime > MAXATATIME)
996 BlocksThisTime = MAXATATIME;
997
998 /* Yes, start a sector read
999 */
1000 sysace_inton(sc);
1001 error = sysace_start(sc,
1002 SAC_CMD_READMEMCARDDATA,
1003 (uint32_t)start_sector, /* BUGBUG trims here, no warn. */
1004 BlocksThisTime);
1005 /* And wait until done, if ok
1006 */
1007 if (!FAILED(error)) {
1008 start_sector += BlocksThisTime;
1009 /* Might be called during autoconf, no interrupts */
1010 /* BUGBUG timeouts! */
1011 if (cold) {
1012 do {
1013 DELAY(10);
1014 Status = sc->sc_dr->STATUS;
1015 } while (0 == (Status & (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)));
1016 } else {
1017 while (sc->hw_busy) {
1018 error = tsleep(&sc->media_has_changed, PRIBIO, "aceread", 0);
1019 }
1020 }
1021 }
1022
1023 /* Are we doing ok
1024 */
1025 if (!FAILED(error)) {
1026
1027 /* Get the data out of the ACE
1028 */
1029 for (i = 0; i < (BlocksThisTime << CF_SECBITS); i += 4) {
1030
1031 /* Make sure the FIFO is ready
1032 */
1033 for (j = 0; j < 10; j++) {
1034 Status = sc->sc_dr->STATUS;
1035 if (Status & SAC_DATABUFRDY)
1036 break;
1037 DELAY(1000);
1038 }
1039
1040 /* Got it?
1041 */
1042 if (Status & SAC_DATABUFRDY) {
1043 uint32_t Data32;
1044
1045 Data32 = sc->sc_dr->DATABUFREG[0];
1046 Data32 = le32toh(Data32);
1047 memcpy(buffer+i,&Data32,4);
1048 }
1049 else
1050 {
1051 /* Ooops, get out of here
1052 */
1053 DBGME(DEBUG_ERRORS,printf("Sysace::READ timeout\n"));
1054 SysaceDumpRegisters(sc->sc_dr);
1055 error = ETIMEDOUT;
1056 break;
1057 }
1058 }
1059
1060 /* Still doing ok?
1061 */
1062 if (!FAILED(error)) {
1063 nblocks -= BlocksThisTime;
1064 SizeRead += BlocksThisTime;
1065 buffer += BlocksThisTime << CF_SECBITS;
1066 }
1067 else
1068 /* remember this jic */
1069 sc->sc_bio.r_error = Status;
1070 }
1071
1072 /* Free the ACE for the JTAG, just in case */
1073 sysace_unlock_registers(sc);
1074
1075 /* Are we done yet?
1076 */
1077 if (nblocks == 0)
1078 break;
1079 }
1080
1081 if (pSizeRead)
1082 *pSizeRead = SizeRead;
1083 return error;
1084 }
1085
1086 /* Write SIZE bytes to device.
1087 */
1088 static int sysace_write_at (struct ace_softc *sc,
1089 daddr_t start_sector, char *buffer, size_t nblocks,
1090 size_t * pSizeWritten)
1091 {
1092 int error;
1093 uint32_t BlocksThisTime;
1094 uint32_t Status = 0, SizeWritten = 0;
1095 uint32_t i, j;
1096
1097 DBGME(DEBUG_XFERS|DEBUG_WRITES,printf("SysaceWriteAt(%p %qx %p %zd %p)\n",
1098 sc, start_sector, buffer, nblocks, pSizeWritten));
1099
1100 /* Validate & trim arguments
1101 */
1102 error = sysace_validate(sc, start_sector, &nblocks);
1103
1104 /* Repeat until we are done or error
1105 */
1106 while (error == 0) {
1107
1108 /* .. one sector at a time
1109 * BUGBUG Supposedly we can do up to 256 sectors?
1110 */
1111 BlocksThisTime = nblocks;
1112 if (BlocksThisTime > MAXATATIME)
1113 BlocksThisTime = MAXATATIME;
1114
1115 /* Yes, start a sector write
1116 */
1117 sysace_inton(sc);
1118 error = sysace_start(sc,
1119 SAC_CMD_WRITEMEMCARDDATA,
1120 (uint32_t)start_sector, /* BUGBUG trims here, no warn. */
1121 BlocksThisTime);
1122 /* And wait until done, if ok
1123 */
1124 if (!FAILED(error)) {
1125 start_sector += BlocksThisTime;
1126 /* BUGBUG timeouts! */
1127 while (sc->hw_busy) {
1128 error = tsleep(&sc->media_has_changed, PRIBIO, "acewrite", 0);
1129 }
1130 }
1131
1132 /* Are we doing ok
1133 */
1134 if (!FAILED(error)) {
1135
1136 /* Get the data out to the ACE
1137 */
1138 for (i = 0; i < (BlocksThisTime << CF_SECBITS); i += 4) {
1139
1140 /* Make sure the FIFO is ready
1141 */
1142 for (j = 0; j < 10; j++) {
1143 Status = sc->sc_dr->STATUS;
1144 if (Status & SAC_DATABUFRDY)
1145 break;
1146 DELAY(1000);
1147 }
1148
1149 /* Got it?
1150 */
1151 if (Status & SAC_DATABUFRDY) {
1152 uint32_t Data32;
1153
1154 memcpy(&Data32,buffer+i,4);
1155 Data32 = htole32(Data32);
1156 sc->sc_dr->DATABUFREG[0] = Data32;
1157 }
1158 else
1159 {
1160 /* Ooops, get out of here
1161 */
1162 DBGME(DEBUG_ERRORS,printf("Sysace::WRITE timeout\n"));
1163 SysaceDumpRegisters(sc->sc_dr);
1164 error = ETIMEDOUT;
1165 /* remember this jic */
1166 sc->sc_bio.r_error = Status;
1167 break;
1168 }
1169 }
1170
1171 /* Still doing ok?
1172 */
1173 if (!FAILED(error)) {
1174 nblocks -= BlocksThisTime;
1175 SizeWritten += BlocksThisTime;
1176 buffer += BlocksThisTime << CF_SECBITS;
1177 }
1178 }
1179
1180 /* We need to wait until the device is ready for the next command
1181 * Experimentation shows that it can take longer than 10msec.
1182 */
1183 if (!FAILED(error)) {
1184 for (j = 0; j < 300; j++) {
1185 Status = sc->sc_dr->STATUS;
1186 if (Status & SAC_RDYFORCFCMD)
1187 break;
1188 (void) tsleep(&sc->media_has_changed, PRIBIO, "acewrite", 2);
1189 }
1190 if (! (Status & SAC_RDYFORCFCMD)) {
1191 DBGME(DEBUG_ERRORS,printf("Sysace::WRITE-COMPLETE timeout St=%x\n", Status));
1192 SysaceDumpRegisters(sc->sc_dr);
1193 /* Ignore, we'll handle it the next time around
1194 * BUGBUG To be revised along with non-existant error handling
1195 */
1196 }
1197 }
1198
1199 /* Free the ACE for the JTAG, just in case */
1200 sysace_unlock_registers(sc);
1201
1202 /* Are we done yet?
1203 */
1204 if (nblocks == 0)
1205 break;
1206 }
1207
1208 if (pSizeWritten)
1209 *pSizeWritten = SizeWritten;
1210 return error;
1211 }
1212
1213 int
1214 ace_ebus_intr(void *cookie, void *f)
1215 {
1216 struct ace_softc *sc = cookie;
1217 uint32_t Control;
1218
1219 /* Turn off interrupts and ACK them
1220 */
1221 sysace_intoff(sc);
1222
1223 Control = sc->sc_dr->CONTROLREG & (~(SAC_RESETIRQ|SAC_INTERRUPTS));
1224 sc->sc_dr->CONTROLREG = Control | SAC_RESETIRQ;
1225 sc->sc_dr->CONTROLREG = Control;
1226
1227 /* ... read status and do whatever ... */
1228
1229 sc->hw_busy = FALSE;
1230 wakeup(&sc->media_has_changed);
1231 return 1;
1232 }
1233
1234 #ifdef USE_ACE_FOR_RECONFIG
1235 static int sysace_send_config(struct ace_softc *sc,
1236 uint32_t *Data, unsigned int nBytes)
1237 {
1238 struct _Sac *Interface = sc->sc_dr;
1239 unsigned int i, j, nWords;
1240 uint32_t CtlWas;
1241 uint32_t Status;
1242
1243 CtlWas = Interface->CONTROLREG;
1244
1245 /* Set the bits but in RESET (pag 49-50 of specs)*/
1246 #define CFGCMD (SAC_FORCELOCKREQ | SAC_LOCKREQ | SAC_CFGSEL | \
1247 SAC_FORCECFGMODE |/* SAC_CFGMODE |*/ SAC_CFGSTART)
1248
1249 Interface->CONTROLREG = CFGCMD | SAC_CFGRESET;
1250
1251 /* Take it out of RESET */
1252 Interface->CONTROLREG = CFGCMD;
1253
1254 /* Must wait till it says READY
1255 * It can take a looong time
1256 */
1257 for (j = 0; j < 1000; j++) {
1258 Status = Interface->STATUS;
1259 if (Status & SAC_RDYFORCFCMD)
1260 break;
1261 DELAY(1000);
1262 }
1263
1264 if (0 == (Status & SAC_RDYFORCFCMD)) {
1265 DBGME(DEBUG_ERRORS,printf("Sysace::CMD error %x (j=%d)\n", Status, j));
1266 goto Error;
1267 }
1268
1269 /* Get the data out to the ACE
1270 */
1271 #define ACEROUNDUP 32
1272 nBytes = (nBytes + ACEROUNDUP - 1) & ~(ACEROUNDUP-1);
1273 nWords = (nBytes + 3) / 4;
1274 DBGME(DEBUG_FUNCS,printf("Sending %d bytes (as %d words) to %p ",
1275 nBytes, nWords, Interface));
1276 for (i = 0; i < nWords; i += 1/*word*/) {
1277
1278 /* Stop on errors */
1279 Status = Interface->ERRORREG;
1280 if (Status) {
1281 /* Ooops, get out of here
1282 */
1283 DBGME(DEBUG_ERRORS,printf("Sysace::CFG error %x (i=%d)\n", Status, i));
1284 goto Error;
1285 }
1286
1287 /* Make sure the FIFO is ready
1288 */
1289 for (j = 0; j < 100; j++) {
1290 Status = Interface->STATUS;
1291 if (Status & SAC_DATABUFRDY)
1292 break;
1293 DELAY(1000);
1294 }
1295
1296 /* Got it?
1297 */
1298 if (Status & SAC_DATABUFRDY) {
1299 uint32_t Data32;
1300
1301 Data32 = Data[i];
1302 Data32 = htole32(Data32);
1303 Interface->DATABUFREG[0] = Data32;
1304 }
1305 else
1306 {
1307 /* Ooops, get out of here
1308 */
1309 DBGME(DEBUG_ERRORS,printf("Sysace::WRITE timeout %x (i=%d)\n", Status, i));
1310 goto Error;
1311 }
1312 }
1313 DBGME(DEBUG_FUNCS,printf("done ok.\n"));
1314
1315 /* Put it back the way it was (try to.. :-( )*/
1316 Interface->CONTROLREG = CtlWas;
1317 return 0;
1318
1319 Error:
1320 SysaceDumpRegisters(Interface);
1321 Interface->CONTROLREG = CtlWas;
1322 return (EIO);
1323 }
1324 #endif /* USE_ACE_FOR_RECONFIG */
1325
1326
1327 /* Rest of code lifted with mods from the dev\ata\wd.c driver
1328 */
1329
1330 /* $NetBSD: ace_ebus.c,v 1.1 2011/01/26 01:18:50 pooka Exp $ */
1331
1332 /*
1333 * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
1334 *
1335 * Redistribution and use in source and binary forms, with or without
1336 * modification, are permitted provided that the following conditions
1337 * are met:
1338 * 1. Redistributions of source code must retain the above copyright
1339 * notice, this list of conditions and the following disclaimer.
1340 * 2. Redistributions in binary form must reproduce the above copyright
1341 * notice, this list of conditions and the following disclaimer in the
1342 * documentation and/or other materials provided with the distribution.
1343 * 3. All advertising materials mentioning features or use of this software
1344 * must display the following acknowledgement:
1345 * This product includes software developed by Manuel Bouyer.
1346 * 4. The name of the author may not be used to endorse or promote products
1347 * derived from this software without specific prior written permission.
1348 *
1349 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1350 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1351 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1352 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1353 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1354 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1355 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1356 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1357 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1358 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1359 */
1360
1361 /*-
1362 * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
1363 * All rights reserved.
1364 *
1365 * This code is derived from software contributed to The NetBSD Foundation
1366 * by Charles M. Hannum and by Onno van der Linden.
1367 *
1368 * Redistribution and use in source and binary forms, with or without
1369 * modification, are permitted provided that the following conditions
1370 * are met:
1371 * 1. Redistributions of source code must retain the above copyright
1372 * notice, this list of conditions and the following disclaimer.
1373 * 2. Redistributions in binary form must reproduce the above copyright
1374 * notice, this list of conditions and the following disclaimer in the
1375 * documentation and/or other materials provided with the distribution.
1376 * 3. All advertising materials mentioning features or use of this software
1377 * must display the following acknowledgement:
1378 * This product includes software developed by the NetBSD
1379 * Foundation, Inc. and its contributors.
1380 * 4. Neither the name of The NetBSD Foundation nor the names of its
1381 * contributors may be used to endorse or promote products derived
1382 * from this software without specific prior written permission.
1383 *
1384 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1385 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1386 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1387 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
1388 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1389 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1390 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1391 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1392 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1393 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1394 * POSSIBILITY OF SUCH DAMAGE.
1395 */
1396
1397 static const char ST506[] = "ST506";
1398
1399 #define ACEIORETRIES_SINGLE 4 /* number of retries before single-sector */
1400 #define ACEIORETRIES 5 /* number of retries before giving up */
1401 #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */
1402
1403 #define ACEUNIT(dev) DISKUNIT(dev)
1404 #define ACEPART(dev) DISKPART(dev)
1405 #define ACEMINOR(unit, part) DISKMINOR(unit, part)
1406 #define MAKEACEDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
1407
1408 #define ACELABELDEV(dev) (MAKEACEDEV(major(dev), ACEUNIT(dev), RAW_PART))
1409
1410 void aceperror(const struct ace_softc *);
1411
1412 extern struct cfdriver ace_cd;
1413
1414 dev_type_open(aceopen);
1415 dev_type_close(aceclose);
1416 dev_type_read(aceread);
1417 dev_type_write(acewrite);
1418 dev_type_ioctl(aceioctl);
1419 dev_type_strategy(acestrategy);
1420 dev_type_dump(acedump);
1421 dev_type_size(acesize);
1422
1423 const struct bdevsw ace_bdevsw = {
1424 aceopen, aceclose, acestrategy, aceioctl, acedump, acesize, D_DISK
1425 };
1426
1427 const struct cdevsw ace_cdevsw = {
1428 aceopen, aceclose, aceread, acewrite, aceioctl,
1429 nostop, notty, nopoll, nommap, nokqfilter, D_DISK
1430 };
1431
1432 void acegetdefaultlabel(struct ace_softc *, struct disklabel *);
1433 void acegetdisklabel(struct ace_softc *);
1434 void acestart(void *);
1435 void __acestart(struct ace_softc*, struct buf *);
1436 void acerestart(void *);
1437
1438 struct dkdriver acedkdriver = { acestrategy, minphys };
1439
1440 #ifdef HAS_BAD144_HANDLING
1441 static void bad144intern(struct ace_softc *);
1442 #endif
1443
1444 void
1445 aceattach(struct ace_softc *ace)
1446 {
1447 struct device *self = ace->sc_dev;
1448 char tbuf[41], pbuf[9], c, *p, *q;
1449 int i, blank;
1450 DEBUG_PRINT(("aceattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
1451
1452 callout_init(&ace->sc_restart_ch, 0);
1453 bufq_alloc(&ace->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
1454
1455 ace->openings = 1; /* wazziz?*/
1456 ace->sc_multi = MAXATATIME;
1457
1458 aprint_naive("\n");
1459
1460 /* setup all required fields so that if the attach fails we are ok */
1461 ace->sc_dk.dk_driver = &acedkdriver;
1462 ace->sc_dk.dk_name = device_xname(ace->sc_dev);
1463
1464 /* read our drive info */
1465 if (sysace_attach(ace) != 0) {
1466 aprint_error_dev(ace->sc_dev, "attach failed\n");
1467 return;
1468 }
1469
1470 aprint_normal_dev(ace->sc_dev, "drive supports %d-sector PIO xfers\n",
1471 ace->sc_multi);
1472
1473 for (blank = 0, p = ace->sc_params.ModelNumber, q = tbuf, i = 0;
1474 i < sizeof(ace->sc_params.ModelNumber); i++) {
1475 c = *p++;
1476 if (c == '\0')
1477 break;
1478 if (c != ' ') {
1479 if (blank) {
1480 *q++ = ' ';
1481 blank = 0;
1482 }
1483 *q++ = c;
1484 } else
1485 blank = 1;
1486 }
1487 *q++ = '\0';
1488
1489 aprint_normal_dev(ace->sc_dev, "card is <%s>\n", tbuf);
1490
1491 format_bytes(pbuf, sizeof(pbuf), ace->sc_capacity * DEV_BSIZE);
1492 aprint_normal("%s: %s, %d cyl, %d head, %d sec, "
1493 "%d bytes/sect x %llu sectors\n",
1494 self->dv_xname, pbuf,
1495 (int)(ace->sc_capacity /
1496 (ace->sc_params.CurrentNumberOfHeads * ace->sc_params.CurrentSectorsPerTrack)),
1497 ace->sc_params.CurrentNumberOfHeads, ace->sc_params.CurrentSectorsPerTrack,
1498 DEV_BSIZE, (unsigned long long)ace->sc_capacity);
1499
1500 /*
1501 * Attach the disk structure. We fill in dk_info later.
1502 */
1503 disk_attach(&ace->sc_dk);
1504
1505 #if NRND > 0
1506 rnd_attach_source(&ace->rnd_source, device_xname(ace->sc_dev),
1507 RND_TYPE_DISK, 0);
1508 #endif
1509
1510 }
1511
1512 int
1513 aceactivate(struct device *self, enum devact act)
1514 {
1515 int rv = 0;
1516
1517 switch (act) {
1518 case DVACT_DEACTIVATE:
1519 /*
1520 * Nothing to do; we key off the device's DVF_ACTIVATE.
1521 */
1522 break;
1523 default:
1524 rv = EOPNOTSUPP;
1525 }
1526 return (rv);
1527 }
1528
1529 int
1530 acedetach(struct device *self, int flags)
1531 {
1532 struct ace_softc *sc = device_private(self);
1533 int s, bmaj, cmaj, i, mn;
1534
1535 /* locate the major number */
1536 bmaj = bdevsw_lookup_major(&ace_bdevsw);
1537 cmaj = cdevsw_lookup_major(&ace_cdevsw);
1538
1539 /* Nuke the vnodes for any open instances. */
1540 for (i = 0; i < MAXPARTITIONS; i++) {
1541 mn = ACEMINOR(device_unit(self), i);
1542 vdevgone(bmaj, mn, mn, VBLK);
1543 vdevgone(cmaj, mn, mn, VCHR);
1544 }
1545
1546 /* Delete all of our wedges. */
1547 dkwedge_delall(&sc->sc_dk);
1548
1549 s = splbio();
1550
1551 /* Kill off any queued buffers. */
1552 bufq_drain(sc->sc_q);
1553
1554 bufq_free(sc->sc_q);
1555 //sc->atabus->ata_killpending(sc->drvp);
1556
1557 splx(s);
1558
1559 /* Detach disk. */
1560 disk_detach(&sc->sc_dk);
1561
1562 #if NRND > 0
1563 /* Unhook the entropy source. */
1564 rnd_detach_source(&sc->rnd_source);
1565 #endif
1566
1567 //sc->drvp->drive_flags = 0; /* no drive any more here */
1568
1569 return (0);
1570 }
1571
1572 /*
1573 * Read/write routine for a buffer. Validates the arguments and schedules the
1574 * transfer. Does not wait for the transfer to complete.
1575 */
1576 void
1577 acestrategy(struct buf *bp)
1578 {
1579 struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(bp->b_dev));
1580 struct disklabel *lp;
1581 daddr_t blkno;
1582 int s;
1583
1584 if (ace == NULL) {
1585 bp->b_error = ENXIO;
1586 biodone(bp);
1587 return;
1588 }
1589 lp = ace->sc_dk.dk_label;
1590
1591 DEBUG_PRINT(("acestrategy (%s) %lld\n", device_xname(ace->sc_dev), bp->b_blkno), DEBUG_XFERS);
1592
1593 /* Valid request? */
1594 if (bp->b_blkno < 0 ||
1595 (bp->b_bcount % lp->d_secsize) != 0 ||
1596 (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
1597 bp->b_error = EINVAL;
1598 goto done;
1599 }
1600
1601 /* If device invalidated (e.g. media change, door open), error. */
1602 if ((ace->sc_flags & ACEF_LOADED) == 0) {
1603 bp->b_error = EIO;
1604 goto done;
1605 }
1606
1607 /* If it's a null transfer, return immediately. */
1608 if (bp->b_bcount == 0)
1609 goto done;
1610
1611 /*
1612 * Do bounds checking, adjust transfer. if error, process.
1613 * If end of partition, just return.
1614 */
1615 if (ACEPART(bp->b_dev) == RAW_PART) {
1616 if (bounds_check_with_mediasize(bp, DEV_BSIZE,
1617 ace->sc_capacity) <= 0)
1618 goto done;
1619 } else {
1620 if (bounds_check_with_label(&ace->sc_dk, bp,
1621 (ace->sc_flags & (ACEF_WLABEL|ACEF_LABELLING)) != 0) <= 0)
1622 goto done;
1623 }
1624
1625 /*
1626 * Now convert the block number to absolute and put it in
1627 * terms of the device's logical block size.
1628 */
1629 if (lp->d_secsize >= DEV_BSIZE)
1630 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
1631 else
1632 blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
1633
1634 if (ACEPART(bp->b_dev) != RAW_PART)
1635 blkno += lp->d_partitions[ACEPART(bp->b_dev)].p_offset;
1636
1637 bp->b_rawblkno = blkno;
1638
1639 /* Queue transfer on drive, activate drive and controller if idle. */
1640 s = splbio();
1641 bufq_put(ace->sc_q, bp);
1642 acestart(ace);
1643 splx(s);
1644 return;
1645 done:
1646 /* Toss transfer; we're done early. */
1647 bp->b_resid = bp->b_bcount;
1648 biodone(bp);
1649 }
1650
1651 /*
1652 * Queue a drive for I/O.
1653 */
1654 void
1655 acestart(void *arg)
1656 {
1657 struct ace_softc *ace = arg;
1658 struct buf *bp = NULL;
1659
1660 DEBUG_PRINT(("acestart %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS);
1661 while (ace->openings > 0) {
1662
1663 /* Is there a buf for us ? */
1664 if ((bp = bufq_get(ace->sc_q)) == NULL)
1665 return;
1666
1667 /*
1668 * Make the command. First lock the device
1669 */
1670 ace->openings--;
1671
1672 ace->retries = 0;
1673 __acestart(ace, bp);
1674 }
1675 }
1676
1677 void
1678 __acestart(struct ace_softc *sc, struct buf *bp)
1679 {
1680 sc->sc_bp = bp;
1681 /*
1682 * If we're retrying, retry in single-sector mode. This will give us
1683 * the sector number of the problem, and will eventually allow the
1684 * transfer to succeed.
1685 */
1686 if (sc->retries >= ACEIORETRIES_SINGLE)
1687 sc->sc_bio.flags = ATA_SINGLE;
1688 else
1689 sc->sc_bio.flags = 0;
1690 if (bp->b_flags & B_READ)
1691 sc->sc_bio.flags |= ATA_READ;
1692 sc->sc_bio.blkno = bp->b_rawblkno;
1693 sc->sc_bio.blkdone = 0;
1694 sc->sc_bio.nbytes = bp->b_bcount;
1695 sc->sc_bio.nblks = bp->b_bcount >> CF_SECBITS;
1696 sc->sc_bio.databuf = bp->b_data;
1697 /* Instrumentation. */
1698 disk_busy(&sc->sc_dk);
1699 sc->active_xfer = bp;
1700 wakeup(&sc->ch_thread);
1701 }
1702
1703 void
1704 acedone(struct ace_softc *ace)
1705 {
1706 struct buf *bp = ace->sc_bp;
1707 const char *errmsg;
1708 int do_perror = 0;
1709
1710 DEBUG_PRINT(("acedone %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS);
1711
1712 if (bp == NULL)
1713 return;
1714
1715 bp->b_resid = ace->sc_bio.nbytes;
1716 switch (ace->sc_bio.error) {
1717 case ETIMEDOUT:
1718 errmsg = "device timeout";
1719 do_perror = 1;
1720 goto retry;
1721 case EBUSY:
1722 case EDOOFUS:
1723 errmsg = "device stuck";
1724 retry: /* Just reset and retry. Can we do more ? */
1725 sysace_reset(ace);
1726 diskerr(bp, "ace", errmsg, LOG_PRINTF,
1727 ace->sc_bio.blkdone, ace->sc_dk.dk_label);
1728 if (ace->retries < ACEIORETRIES)
1729 printf(", retrying");
1730 printf("\n");
1731 if (do_perror)
1732 aceperror(ace);
1733 if (ace->retries < ACEIORETRIES) {
1734 ace->retries++;
1735 callout_reset(&ace->sc_restart_ch, RECOVERYTIME,
1736 acerestart, ace);
1737 return;
1738 }
1739
1740 bp->b_error = EIO;
1741 break;
1742 case 0:
1743 if ((ace->sc_bio.flags & ATA_CORR) || ace->retries > 0)
1744 printf("%s: soft error (corrected)\n",
1745 device_xname(ace->sc_dev));
1746 break;
1747 case ENODEV:
1748 case E2BIG:
1749 bp->b_error = EIO;
1750 break;
1751 }
1752 disk_unbusy(&ace->sc_dk, (bp->b_bcount - bp->b_resid),
1753 (bp->b_flags & B_READ));
1754 #if NRND > 0
1755 rnd_add_uint32(&ace->rnd_source, bp->b_blkno);
1756 #endif
1757 biodone(bp);
1758 ace->openings++;
1759 acestart(ace);
1760 }
1761
1762 void
1763 acerestart(void *v)
1764 {
1765 struct ace_softc *ace = v;
1766 struct buf *bp = ace->sc_bp;
1767 int s;
1768 DEBUG_PRINT(("acerestart %s\n", device_xname(ace->sc_dev)),DEBUG_XFERS);
1769
1770 s = splbio();
1771 __acestart(v, bp);
1772 splx(s);
1773 }
1774
1775 int
1776 aceread(dev_t dev, struct uio *uio, int flags)
1777 {
1778 int r;
1779
1780 DEBUG_PRINT(("aceread\n"), DEBUG_XFERS);
1781 r = physio(acestrategy, NULL, dev, B_READ, minphys, uio);
1782 DEBUG_PRINT(("aceread -> x%x resid=%x\n",r,uio->uio_resid),DEBUG_XFERS);
1783
1784 return r;
1785 }
1786
1787 int
1788 acewrite(dev_t dev, struct uio *uio, int flags)
1789 {
1790
1791 DEBUG_PRINT(("acewrite\n"), DEBUG_XFERS);
1792 return (physio(acestrategy, NULL, dev, B_WRITE, minphys, uio));
1793 }
1794
1795 int
1796 aceopen(dev_t dev, int flag, int fmt, struct lwp *l)
1797 {
1798 struct ace_softc *ace;
1799 int part, error;
1800
1801 DEBUG_PRINT(("aceopen\n"), DEBUG_FUNCS);
1802 ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
1803 if (ace == NULL)
1804 return (ENXIO);
1805
1806 if (! device_is_active(ace->sc_dev))
1807 return (ENODEV);
1808
1809 part = ACEPART(dev);
1810
1811 mutex_enter(&ace->sc_dk.dk_openlock);
1812
1813 /*
1814 * If there are wedges, and this is not RAW_PART, then we
1815 * need to fail.
1816 */
1817 if (ace->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
1818 error = EBUSY;
1819 goto bad;
1820 }
1821
1822 if (ace->sc_dk.dk_openmask != 0) {
1823 /*
1824 * If any partition is open, but the disk has been invalidated,
1825 * disallow further opens.
1826 */
1827 if ((ace->sc_flags & ACEF_LOADED) == 0) {
1828 error = EIO;
1829 goto bad;
1830 }
1831 } else {
1832 if ((ace->sc_flags & ACEF_LOADED) == 0) {
1833 ace->sc_flags |= ACEF_LOADED;
1834
1835 /* Load the physical device parameters. */
1836 if (ace->sc_capacity == 0) {
1837 error = sysace_identify(ace);
1838 if (error) goto bad;
1839 }
1840
1841 /* Load the partition info if not already loaded. */
1842 acegetdisklabel(ace);
1843 }
1844 }
1845
1846 /* Check that the partition exists. */
1847 if (part != RAW_PART &&
1848 (part >= ace->sc_dk.dk_label->d_npartitions ||
1849 ace->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
1850 error = ENXIO;
1851 goto bad;
1852 }
1853
1854 /* Insure only one open at a time. */
1855 switch (fmt) {
1856 case S_IFCHR:
1857 ace->sc_dk.dk_copenmask |= (1 << part);
1858 break;
1859 case S_IFBLK:
1860 ace->sc_dk.dk_bopenmask |= (1 << part);
1861 break;
1862 }
1863 ace->sc_dk.dk_openmask =
1864 ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask;
1865
1866 mutex_exit(&ace->sc_dk.dk_openlock);
1867 return 0;
1868
1869 bad:
1870 mutex_exit(&ace->sc_dk.dk_openlock);
1871 return error;
1872 }
1873
1874 int
1875 aceclose(dev_t dev, int flag, int fmt, struct lwp *l)
1876 {
1877 struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
1878 int part = ACEPART(dev);
1879
1880 DEBUG_PRINT(("aceclose\n"), DEBUG_FUNCS);
1881 if (ace == NULL)
1882 return ENXIO;
1883
1884 mutex_enter(&ace->sc_dk.dk_openlock);
1885
1886 switch (fmt) {
1887 case S_IFCHR:
1888 ace->sc_dk.dk_copenmask &= ~(1 << part);
1889 break;
1890 case S_IFBLK:
1891 ace->sc_dk.dk_bopenmask &= ~(1 << part);
1892 break;
1893 }
1894 ace->sc_dk.dk_openmask =
1895 ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask;
1896
1897 if (ace->sc_dk.dk_openmask == 0) {
1898
1899 if (! (ace->sc_flags & ACEF_KLABEL))
1900 ace->sc_flags &= ~ACEF_LOADED;
1901
1902 }
1903
1904 mutex_exit(&ace->sc_dk.dk_openlock);
1905 return 0;
1906 }
1907
1908 void
1909 acegetdefaultlabel(struct ace_softc *ace, struct disklabel *lp)
1910 {
1911
1912 DEBUG_PRINT(("acegetdefaultlabel\n"), DEBUG_FUNCS);
1913 memset(lp, 0, sizeof(struct disklabel));
1914
1915 lp->d_secsize = DEV_BSIZE;
1916 lp->d_ntracks = ace->sc_params.CurrentNumberOfHeads;
1917 lp->d_nsectors = ace->sc_params.CurrentSectorsPerTrack;
1918 lp->d_ncylinders = ace->sc_capacity /
1919 (ace->sc_params.CurrentNumberOfHeads * ace->sc_params.CurrentSectorsPerTrack);
1920 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1921
1922 lp->d_type = DTYPE_ST506; /* ?!? */
1923
1924 strncpy(lp->d_typename, ace->sc_params.ModelNumber, 16);
1925 strncpy(lp->d_packname, "fictitious", 16);
1926 if (ace->sc_capacity > UINT32_MAX)
1927 lp->d_secperunit = UINT32_MAX;
1928 else
1929 lp->d_secperunit = ace->sc_capacity;
1930 lp->d_rpm = 3600;
1931 lp->d_interleave = 1;
1932 lp->d_flags = 0;
1933
1934 lp->d_partitions[RAW_PART].p_offset = 0;
1935 lp->d_partitions[RAW_PART].p_size =
1936 lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
1937 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
1938 lp->d_npartitions = RAW_PART + 1;
1939
1940 lp->d_magic = DISKMAGIC;
1941 lp->d_magic2 = DISKMAGIC;
1942 lp->d_checksum = dkcksum(lp);
1943 }
1944
1945 /*
1946 * Fabricate a default disk label, and try to read the correct one.
1947 */
1948 void
1949 acegetdisklabel(struct ace_softc *ace)
1950 {
1951 struct disklabel *lp = ace->sc_dk.dk_label;
1952 const char *errstring;
1953
1954 DEBUG_PRINT(("acegetdisklabel\n"), DEBUG_FUNCS);
1955
1956 memset(ace->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
1957
1958 acegetdefaultlabel(ace, lp);
1959
1960 #ifdef HAS_BAD144_HANDLING
1961 ace->sc_bio.badsect[0] = -1;
1962 #endif
1963
1964 errstring = readdisklabel(MAKEACEDEV(0, device_unit(ace->sc_dev),
1965 RAW_PART), acestrategy, lp,
1966 ace->sc_dk.dk_cpulabel);
1967 if (errstring) {
1968 printf("%s: %s\n", device_xname(ace->sc_dev), errstring);
1969 return;
1970 }
1971
1972 #if DEBUG
1973 if (ACE_DEBUG(DEBUG_WRITES)) {
1974 int i, n = ace->sc_dk.dk_label->d_npartitions;
1975 printf("%s: %d parts\n", device_xname(ace->sc_dev), n);
1976 for (i = 0; i < n; i++) {
1977 printf("\t[%d]: t=%x s=%d o=%d\n", i,
1978 ace->sc_dk.dk_label->d_partitions[i].p_fstype,
1979 ace->sc_dk.dk_label->d_partitions[i].p_size,
1980 ace->sc_dk.dk_label->d_partitions[i].p_offset);
1981 }
1982 }
1983 #endif
1984
1985 #ifdef HAS_BAD144_HANDLING
1986 if ((lp->d_flags & D_BADSECT) != 0)
1987 bad144intern(ace);
1988 #endif
1989 }
1990
1991 void
1992 aceperror(const struct ace_softc *ace)
1993 {
1994 const char *devname = device_xname(ace->sc_dev);
1995 u_int32_t Status = ace->sc_bio.r_error;
1996
1997 printf("%s: (", devname);
1998
1999 if (Status == 0)
2000 printf("error not notified");
2001 else
2002 printf("status=x%x", Status);
2003
2004 printf(")\n");
2005 }
2006
2007 int
2008 aceioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
2009 {
2010 struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
2011 int error = 0, s;
2012
2013 DEBUG_PRINT(("aceioctl\n"), DEBUG_FUNCS);
2014
2015 if ((ace->sc_flags & ACEF_LOADED) == 0)
2016 return EIO;
2017
2018 error = disk_ioctl(&ace->sc_dk, xfer, addr, flag, l);
2019 if (error != EPASSTHROUGH)
2020 return (error);
2021
2022 switch (xfer) {
2023 #ifdef HAS_BAD144_HANDLING
2024 case DIOCSBAD:
2025 if ((flag & FWRITE) == 0)
2026 return EBADF;
2027 ace->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
2028 ace->sc_dk.dk_label->d_flags |= D_BADSECT;
2029 bad144intern(ace);
2030 return 0;
2031 #endif
2032 case DIOCGDINFO:
2033 *(struct disklabel *)addr = *(ace->sc_dk.dk_label);
2034 return 0;
2035
2036 case DIOCGPART:
2037 ((struct partinfo *)addr)->disklab = ace->sc_dk.dk_label;
2038 ((struct partinfo *)addr)->part =
2039 &ace->sc_dk.dk_label->d_partitions[ACEPART(dev)];
2040 return 0;
2041
2042 case DIOCWDINFO:
2043 case DIOCSDINFO:
2044 {
2045 struct disklabel *lp;
2046
2047 if ((flag & FWRITE) == 0)
2048 return EBADF;
2049
2050 lp = (struct disklabel *)addr;
2051
2052 mutex_enter(&ace->sc_dk.dk_openlock);
2053 ace->sc_flags |= ACEF_LABELLING;
2054
2055 error = setdisklabel(ace->sc_dk.dk_label,
2056 lp, /*ace->sc_dk.dk_openmask : */0,
2057 ace->sc_dk.dk_cpulabel);
2058 if (error == 0) {
2059 if (xfer == DIOCWDINFO)
2060 error = writedisklabel(ACELABELDEV(dev),
2061 acestrategy, ace->sc_dk.dk_label,
2062 ace->sc_dk.dk_cpulabel);
2063 }
2064
2065 ace->sc_flags &= ~ACEF_LABELLING;
2066 mutex_exit(&ace->sc_dk.dk_openlock);
2067 return error;
2068 }
2069
2070 case DIOCKLABEL:
2071 if (*(int *)addr)
2072 ace->sc_flags |= ACEF_KLABEL;
2073 else
2074 ace->sc_flags &= ~ACEF_KLABEL;
2075 return 0;
2076
2077 case DIOCWLABEL:
2078 if ((flag & FWRITE) == 0)
2079 return EBADF;
2080 if (*(int *)addr)
2081 ace->sc_flags |= ACEF_WLABEL;
2082 else
2083 ace->sc_flags &= ~ACEF_WLABEL;
2084 return 0;
2085
2086 case DIOCGDEFLABEL:
2087 acegetdefaultlabel(ace, (struct disklabel *)addr);
2088 return 0;
2089
2090 case DIOCCACHESYNC:
2091 return 0;
2092
2093 case DIOCAWEDGE:
2094 {
2095 struct dkwedge_info *dkw = (void *) addr;
2096
2097 if ((flag & FWRITE) == 0)
2098 return (EBADF);
2099
2100 /* If the ioctl happens here, the parent is us. */
2101 strcpy(dkw->dkw_parent, device_xname(ace->sc_dev));
2102 return (dkwedge_add(dkw));
2103 }
2104
2105 case DIOCDWEDGE:
2106 {
2107 struct dkwedge_info *dkw = (void *) addr;
2108
2109 if ((flag & FWRITE) == 0)
2110 return (EBADF);
2111
2112 /* If the ioctl happens here, the parent is us. */
2113 strcpy(dkw->dkw_parent, device_xname(ace->sc_dev));
2114 return (dkwedge_del(dkw));
2115 }
2116
2117 case DIOCLWEDGES:
2118 {
2119 struct dkwedge_list *dkwl = (void *) addr;
2120
2121 return (dkwedge_list(&ace->sc_dk, dkwl, l));
2122 }
2123
2124 case DIOCGSTRATEGY:
2125 {
2126 struct disk_strategy *dks = (void *)addr;
2127
2128 s = splbio();
2129 strlcpy(dks->dks_name, bufq_getstrategyname(ace->sc_q),
2130 sizeof(dks->dks_name));
2131 splx(s);
2132 dks->dks_paramlen = 0;
2133
2134 return 0;
2135 }
2136
2137 case DIOCSSTRATEGY:
2138 {
2139 struct disk_strategy *dks = (void *)addr;
2140 struct bufq_state *new;
2141 struct bufq_state *old;
2142
2143 if ((flag & FWRITE) == 0) {
2144 return EBADF;
2145 }
2146 if (dks->dks_param != NULL) {
2147 return EINVAL;
2148 }
2149 dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
2150 error = bufq_alloc(&new, dks->dks_name,
2151 BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
2152 if (error) {
2153 return error;
2154 }
2155 s = splbio();
2156 old = ace->sc_q;
2157 bufq_move(new, old);
2158 ace->sc_q = new;
2159 splx(s);
2160 bufq_free(old);
2161
2162 return 0;
2163 }
2164
2165 #ifdef USE_ACE_FOR_RECONFIG
2166 /* Ok, how do I get this standardized [nothing to do with disks either] */
2167 #define DIOC_FPGA_RECONFIGURE _IOW('d',166, struct ioctl_pt)
2168 case DIOC_FPGA_RECONFIGURE:
2169 {
2170 /* BUGBUG This is totally wrong, we need to fault in all data in advance.
2171 * Otherwise we get back here with the sysace in a bad state (its NOT reentrant!)
2172 */
2173 struct ioctl_pt *pt = (struct ioctl_pt *)addr;
2174 return sysace_send_config(ace,(uint32_t*)pt->data,pt->com);
2175 }
2176 #endif /* USE_ACE_FOR_RECONFIG */
2177
2178 default:
2179 /* NB: we get a DIOCGWEDGEINFO, but nobody else handles it either */
2180 DEBUG_PRINT(("aceioctl: unsup x%lx\n", xfer), DEBUG_FUNCS);
2181 return ENOTTY;
2182 }
2183 }
2184
2185 int
2186 acesize(dev_t dev)
2187 {
2188 struct ace_softc *ace;
2189 int part, omask;
2190 int size;
2191
2192 DEBUG_PRINT(("acesize\n"), DEBUG_FUNCS);
2193
2194 ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
2195 if (ace == NULL)
2196 return (-1);
2197
2198 part = ACEPART(dev);
2199 omask = ace->sc_dk.dk_openmask & (1 << part);
2200
2201 if (omask == 0 && aceopen(dev, 0, S_IFBLK, NULL) != 0)
2202 return (-1);
2203 if (ace->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
2204 size = -1;
2205 else
2206 size = ace->sc_dk.dk_label->d_partitions[part].p_size *
2207 (ace->sc_dk.dk_label->d_secsize / DEV_BSIZE);
2208 if (omask == 0 && aceclose(dev, 0, S_IFBLK, NULL) != 0)
2209 return (-1);
2210 return (size);
2211 }
2212
2213 /* #define ACE_DUMP_NOT_TRUSTED if you just want to watch */
2214 #define ACE_DUMP_NOT_TRUSTED
2215 static int acedoingadump = 0;
2216
2217 /*
2218 * Dump core after a system crash.
2219 */
2220 int
2221 acedump(dev_t dev, daddr_t blkno, void *va, size_t size)
2222 {
2223 struct ace_softc *ace; /* disk unit to do the I/O */
2224 struct disklabel *lp; /* disk's disklabel */
2225 int part, err;
2226 int nblks; /* total number of sectors left to write */
2227
2228 /* Check if recursive dump; if so, punt. */
2229 if (acedoingadump)
2230 return EFAULT;
2231 acedoingadump = 1;
2232
2233 ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
2234 if (ace == NULL)
2235 return (ENXIO);
2236
2237 part = ACEPART(dev);
2238
2239 /* Convert to disk sectors. Request must be a multiple of size. */
2240 lp = ace->sc_dk.dk_label;
2241 if ((size % lp->d_secsize) != 0)
2242 return EFAULT;
2243 nblks = size / lp->d_secsize;
2244 blkno = blkno / (lp->d_secsize / DEV_BSIZE);
2245
2246 /* Check transfer bounds against partition size. */
2247 if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
2248 return EINVAL;
2249
2250 /* Offset block number to start of partition. */
2251 blkno += lp->d_partitions[part].p_offset;
2252
2253 ace->sc_bp = NULL;
2254 ace->sc_bio.blkno = blkno;
2255 ace->sc_bio.flags = ATA_POLL;
2256 ace->sc_bio.nbytes = nblks * lp->d_secsize;
2257 ace->sc_bio.databuf = va;
2258 #ifndef ACE_DUMP_NOT_TRUSTED
2259 ace->active_xfer = bp;
2260 wakeup(&ace->ch_thread);
2261
2262 switch(ace->sc_bio.error) {
2263 case ETIMEDOUT:
2264 printf("acedump: device timed out");
2265 err = EIO;
2266 break;
2267 case 0:
2268 err = 0;
2269 break;
2270 default:
2271 panic("acedump: unknown error type");
2272 }
2273 if (err != 0) {
2274 printf("\n");
2275 return err;
2276 }
2277 #else /* ACE_DUMP_NOT_TRUSTED */
2278 /* Let's just talk about this first... */
2279 device_printf(ace->sc_dev, ": dump addr 0x%p, size %zu blkno %llx\n",
2280 va, size, blkno);
2281 DELAY(500 * 1000); /* half a second */
2282 err = 0;
2283 #endif
2284
2285 acedoingadump = 0;
2286 return 0;
2287 }
2288
2289 #ifdef HAS_BAD144_HANDLING
2290 /*
2291 * Internalize the bad sector table.
2292 */
2293 void
2294 bad144intern(struct ace_softc *ace)
2295 {
2296 struct dkbad *bt = &ace->sc_dk.dk_cpulabel->bad;
2297 struct disklabel *lp = ace->sc_dk.dk_label;
2298 int i = 0;
2299
2300 DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
2301
2302 for (; i < NBT_BAD; i++) {
2303 if (bt->bt_bad[i].bt_cyl == 0xffff)
2304 break;
2305 ace->sc_bio.badsect[i] =
2306 bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
2307 (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
2308 (bt->bt_bad[i].bt_trksec & 0xff);
2309 }
2310 for (; i < NBT_BAD+1; i++)
2311 ace->sc_bio.badsect[i] = -1;
2312 }
2313 #endif
2314
2315 static void
2316 ace_params_to_properties(struct ace_softc *ace)
2317 {
2318 prop_dictionary_t disk_info, odisk_info, geom;
2319 const char *cp;
2320
2321 disk_info = prop_dictionary_create();
2322
2323 cp = ST506;
2324
2325 prop_dictionary_set_cstring_nocopy(disk_info, "type", cp);
2326
2327 geom = prop_dictionary_create();
2328
2329 prop_dictionary_set_uint64(geom, "sectors-per-unit", ace->sc_capacity);
2330
2331 prop_dictionary_set_uint32(geom, "sector-size",
2332 DEV_BSIZE /* XXX 512? */);
2333
2334 prop_dictionary_set_uint16(geom, "sectors-per-track",
2335 ace->sc_params.CurrentSectorsPerTrack);
2336
2337 prop_dictionary_set_uint16(geom, "tracks-per-cylinder",
2338 ace->sc_params.CurrentNumberOfHeads);
2339
2340 prop_dictionary_set_uint64(geom, "cylinders-per-unit",
2341 ace->sc_capacity /
2342 (ace->sc_params.CurrentNumberOfHeads *
2343 ace->sc_params.CurrentSectorsPerTrack));
2344
2345 prop_dictionary_set(disk_info, "geometry", geom);
2346 prop_object_release(geom);
2347
2348 prop_dictionary_set(device_properties(ace->sc_dev),
2349 "disk-info", disk_info);
2350
2351 /*
2352 * Don't release disk_info here; we keep a reference to it.
2353 * disk_detach() will release it when we go away.
2354 */
2355
2356 odisk_info = ace->sc_dk.dk_info;
2357 ace->sc_dk.dk_info = disk_info;
2358 if (odisk_info)
2359 prop_object_release(odisk_info);
2360 }
2361
2362