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