1/*	$NetBSD: ace_ebus.c,v 1.3 2011/11/19 22:51:19 tls 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.3 2011/11/19 22:51:19 tls 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/malloc.h>
47#include <sys/device.h>
48#include <sys/disklabel.h>
49#include <sys/disk.h>
50#include <sys/syslog.h>
51#include <sys/proc.h>
52#include <sys/vnode.h>
53#include <sys/kthread.h>
54#include <sys/lock.h>
55#include <sys/queue.h>
56
57#include <sys/rnd.h>
58
59#include <machine/intr.h>
60#include <machine/bus.h>
61
62#include "locators.h"
63#include <prop/proplib.h>
64
65#include <emips/ebus/ebusvar.h>
66#include <emips/emips/machdep.h>
67#include <machine/emipsreg.h>
68
69/* Structure returned by the Identify command (see CFlash specs)
70 * NB: We only care for the first sector so that is what we define here.
71 * NB: Beware of mis-alignment for all 32bit things
72 */
73typedef struct _CFLASH_IDENTIFY {
74	uint16_t Signature;				/* Word 0 */
75#define CFLASH_SIGNATURE 0x848a
76	uint16_t DefaultNumberOfCylinders;		/* Word 1 */
77	uint16_t Reserved1;				/* Word 2 */
78	uint16_t DefaultNumberOfHeads;			/* Word 3 */
79	uint16_t Obsolete1[2];				/* Word 4 */
80	uint16_t DefaultSectorsPerTrack;		/* Word 6 */
81	uint16_t SectorsPerCard[2];			/* Word 7 */
82	uint16_t Obsolete2;				/* Word 9 */
83	uint8_t  SerialNumber[20]; /* padded, right-justified Word 10 */
84	uint16_t Obsolete3[2];				/* Word 20 */
85	uint16_t EccBytesInRWLong;			/* Word 22 */
86	uint8_t  FirmwareRevision[8];			/* Word 23 */
87	uint8_t  ModelNumber[40];			/* Word 27 */
88	uint16_t SectorsInRWMultiple;			/* Word 47 */
89	uint16_t Reserved2;				/* Word 48 */
90	uint16_t Capabilities;				/* Word 49 */
91	uint16_t Reserved3;				/* Word 50 */
92	uint16_t PioMode;				/* Word 51 */
93	uint16_t Obsolete4;				/* Word 52 */
94	uint16_t FieldValidity;				/* Word 53 */
95	uint16_t CurrentNumberOfCylinders;		/* Word 54 */
96	uint16_t CurrentNumberOfHeads;			/* Word 55 */
97	uint16_t CurrentSectorsPerTrack;		/* Word 56 */
98	uint16_t CurrentCapacity[2];			/* Word 57 */
99	uint16_t MultiSectorSettings;			/* Word 59 */
100	uint16_t NumberOfAddressableSectors[2];		/* Word 60 */
101	uint16_t Reserved4;				/* Word 62 */
102	uint16_t MultiWordDmaTransfer;			/* Word 63 */
103	uint16_t AdvancedPioModes;			/* Word 64 */
104	uint16_t MinimumMultiWordDmaTiming;		/* Word 65 */
105	uint16_t RecommendedMultiWordDmaTiming;		/* Word 66 */
106	uint16_t PioTimingNoFlowControl;		/* Word 67 */
107	uint16_t PioTimingWithFlowControl;		/* Word 68 */
108	uint16_t Reserved5[13];				/* Word 69 */
109	uint16_t FeaturesSupported[3];			/* Word 82 */
110	uint16_t FeaturesEnabled[3];			/* Word 85 */
111	uint16_t UdmaMode;				/* Word 88 */
112	uint16_t SecurityEraseTime;			/* Word 89 */
113	uint16_t EnhancedSecurityEraseTime;		/* Word 90 */
114	uint16_t CurrentPowerManagementValue;		/* Word 91 */
115	uint8_t  Reserved6[72];				/* Word 92-127 */
116	uint8_t  SecondHalf[256];			/* Word 128-255 */
117} CFLASH_IDENTIFY, *PCFLASH_IDENTIFY;
118
119#define SIZEOF_IDENTIFY CF_SECTOR_SIZE /* must be a sector multiple */
120
121/* Instead of dragging in atavar.h.. */
122/*
123 * Parameters/state needed by the controller to perform an ATA bio.
124 */
125struct ace_bio {
126	volatile int flags;/* cmd flags */
127#define	ATA_POLL	0x0002	/* poll for completion */
128#define	ATA_SINGLE	0x0008	/* transfer must be done in singlesector mode */
129#define	ATA_READ	0x0020	/* transfer is a read (otherwise a write) */
130#define	ATA_CORR	0x0040	/* transfer had a corrected error */
131	daddr_t		blkno;	/* block addr */
132	daddr_t		blkdone;/* number of blks transferred */
133	size_t		nblks;	/* number of blocks currently transferring */
134	size_t		nbytes;	/* number of bytes currently transferring */
135	char		*databuf;/* data buffer address */
136	volatile int	error;
137#define	NOERROR		0	/* There was no error (r_error invalid),
138				   else see acedone()*/
139#define FAILED(er) (er != 0)
140#define EDOOFUS EIO
141
142	uint32_t	r_error;/* copy of status register */
143#ifdef HAS_BAD144_HANDLING
144	daddr_t		badsect[127];/* 126 plus trailing -1 marker */
145#endif
146};
147/* End of atavar.h*/
148
149struct ace_softc {
150	/* General disk infos */
151	device_t sc_dev;
152
153	struct disk sc_dk;
154	struct bufq_state *sc_q;
155	struct callout sc_restart_ch;
156
157	/* IDE disk soft states */
158	struct buf *sc_bp; /* buf being transfered */
159	struct buf *active_xfer; /* buf handoff to thread  */
160	/* current transfer data */
161	struct ace_bio sc_bio; /* current transfer */
162
163	struct proc *ch_thread;
164	int ch_flags;
165#define ATACH_SHUTDOWN 0x02        /* thread is shutting down */
166#define ATACH_IRQ_WAIT 0x10        /* thread is waiting for irq */
167#define ATACH_DISABLED 0x80        /* channel is disabled */
168#define ATACH_TH_RUN   0x100       /* the kernel thread is working */
169#define ATACH_TH_RESET 0x200       /* someone ask the thread to reset */
170
171	int openings;
172	int media_has_changed;
173#define    ACECE_MC    0x20    /* media changed */
174#define    ACECE_MCR   0x08    /* media change requested */
175	struct _CFLASH_IDENTIFY sc_params;/* drive characteristics found */
176
177	int sc_flags;
178#define	ACEF_WLABEL	0x004 /* label is writable */
179#define	ACEF_LABELLING	0x008 /* writing label */
180#define ACEF_LOADED	0x010 /* parameters loaded */
181#define ACEF_WAIT	0x020 /* waiting for resources */
182#define ACEF_KLABEL	0x080 /* retain label after 'full' close */
183
184	uint64_t sc_capacity;
185	uint32_t sc_multi; /* max sectors per xfer */
186
187	struct	_Sac   *sc_dr;		/* reg pointers */
188	int hw_busy;
189	int retries; /* number of xfer retry */
190
191	krndsource_t	rnd_source;
192};
193
194int  ace_ebus_match(device_t, cfdata_t, void *);
195void ace_ebus_attach(device_t, device_t, void *);
196void aceattach(struct ace_softc *);
197int	 acedetach(device_t, int);
198int	 aceactivate(device_t, enum devact);
199
200void  acedone(struct ace_softc *);
201static void ace_params_to_properties(struct ace_softc *ace);
202
203CFATTACH_DECL_NEW(ace_ebus, sizeof(struct ace_softc),
204    ace_ebus_match, ace_ebus_attach, acedetach, aceactivate);
205
206int  ace_ebus_intr(void *cookie, void *f);
207
208static void sysace_thread(void *arg);
209
210int
211ace_ebus_match(device_t parent, cfdata_t cf, void *aux)
212{
213	struct ebus_attach_args *d = aux;
214	struct _Sac *sac = (struct _Sac *)d->ia_vaddr;
215
216	if (strcmp("ace", d->ia_name) != 0)
217		return 0;
218	if ((sac == NULL) ||
219	    ((sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE))
220		return 0;
221	return 1;
222}
223
224void
225ace_ebus_attach(device_t parent, device_t self, void *aux)
226{
227	struct ace_softc *ace = device_private(self);
228	struct ebus_attach_args *ia = aux;
229	int error;
230
231	/*
232	 * It's on the baseboard, with a dedicated interrupt line.
233	 */
234	ace->sc_dr = (struct _Sac *)ia->ia_vaddr;
235	ace->sc_dev = self;
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();
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
259static int sysace_attach(struct ace_softc *sc);
260static int sysace_reset(struct ace_softc *sc);
261static int sysace_identify(struct ace_softc *sc);
262static int sysace_lock_registers(struct ace_softc *sc);
263static int sysace_unlock_registers(struct ace_softc *sc);
264static int sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba,
265			uint32_t nSectors);
266static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize);
267static int sysace_read_at (struct ace_softc *sc, daddr_t start_sector,
268			   char *buffer, size_t nblocks, size_t * pSizeRead);
269static 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 */
272static 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
285int 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
294static int
295sysace_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;
327Out:
328	return error;
329}
330
331static void
332sysace_wedges(void *arg);
333extern int	dkwedge_autodiscover;
334
335/*
336 * Aux temp thread to avoid deadlock when doing
337 * the partitio.. ahem wedges thing.
338 */
339static void
340sysace_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();
351
352	DBGME(DEBUG_STATUS, printf("Sysace::thread done for %p\n", sc));
353	kthread_exit(0);
354}
355
356static void
357sysace_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
443typedef char *NAME;
444typedef struct _REGDESC {
445	NAME RegisterName;
446	NAME BitNames[32];
447} REGDESC, *PREGDESC;
448
449static void
450SysacePrintRegister(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
463static uint32_t
464SysaceDumpRegisters(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 */
615static int
616sysace_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 */
672static int
673sysace_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 */
715static int
716sysace_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 */
789static int
790sysace_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 */
847static int
848sysace_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_params_to_properties(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 */
1011static int
1012sysace_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 */
1054uint32_t ace_maxatatime = 255;
1055#define MAXATATIME ace_maxatatime //255 /* BUGBUG test me on real hardware!! */
1056
1057static int
1058sysace_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 */
1190static int
1191sysace_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-existant
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
1336int
1337ace_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
1359static int
1360sysace_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/*	$NetBSD: ace_ebus.c,v 1.3 2011/11/19 22:51:19 tls Exp $ */
1465
1466/*
1467 * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
1468 *
1469 * Redistribution and use in source and binary forms, with or without
1470 * modification, are permitted provided that the following conditions
1471 * are met:
1472 * 1. Redistributions of source code must retain the above copyright
1473 *	notice, this list of conditions and the following disclaimer.
1474 * 2. Redistributions in binary form must reproduce the above copyright
1475 *	notice, this list of conditions and the following disclaimer in the
1476 *	documentation and/or other materials provided with the distribution.
1477 * 3. All advertising materials mentioning features or use of this software
1478 *	must display the following acknowledgement:
1479 *  This product includes software developed by Manuel Bouyer.
1480 * 4. The name of the author may not be used to endorse or promote products
1481 *	derived from this software without specific prior written permission.
1482 *
1483 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1484 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1485 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1486 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1487 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1488 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1489 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1490 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1491 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1492 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1493 */
1494
1495/*-
1496 * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
1497 * All rights reserved.
1498 *
1499 * This code is derived from software contributed to The NetBSD Foundation
1500 * by Charles M. Hannum and by Onno van der Linden.
1501 *
1502 * Redistribution and use in source and binary forms, with or without
1503 * modification, are permitted provided that the following conditions
1504 * are met:
1505 * 1. Redistributions of source code must retain the above copyright
1506 *    notice, this list of conditions and the following disclaimer.
1507 * 2. Redistributions in binary form must reproduce the above copyright
1508 *    notice, this list of conditions and the following disclaimer in the
1509 *    documentation and/or other materials provided with the distribution.
1510 * 3. All advertising materials mentioning features or use of this software
1511 *    must display the following acknowledgement:
1512 *        This product includes software developed by the NetBSD
1513 *        Foundation, Inc. and its contributors.
1514 * 4. Neither the name of The NetBSD Foundation nor the names of its
1515 *    contributors may be used to endorse or promote products derived
1516 *    from this software without specific prior written permission.
1517 *
1518 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1519 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1520 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1521 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
1522 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1523 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1524 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1525 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1526 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1527 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1528 * POSSIBILITY OF SUCH DAMAGE.
1529 */
1530
1531static const char ST506[] = "ST506";
1532
1533#define	ACEIORETRIES_SINGLE 4	/* number of retries before single-sector */
1534#define	ACEIORETRIES	5	/* number of retries before giving up */
1535#define	RECOVERYTIME hz/2	/* time to wait before retrying a cmd */
1536
1537#define	ACEUNIT(dev)		DISKUNIT(dev)
1538#define	ACEPART(dev)		DISKPART(dev)
1539#define	ACEMINOR(unit, part)	DISKMINOR(unit, part)
1540#define	MAKEACEDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
1541
1542#define	ACELABELDEV(dev)	(MAKEACEDEV(major(dev), ACEUNIT(dev), RAW_PART))
1543
1544void	aceperror(const struct ace_softc *);
1545
1546extern struct cfdriver ace_cd;
1547
1548dev_type_open(aceopen);
1549dev_type_close(aceclose);
1550dev_type_read(aceread);
1551dev_type_write(acewrite);
1552dev_type_ioctl(aceioctl);
1553dev_type_strategy(acestrategy);
1554dev_type_dump(acedump);
1555dev_type_size(acesize);
1556
1557const struct bdevsw ace_bdevsw = {
1558	aceopen, aceclose, acestrategy, aceioctl, acedump, acesize, D_DISK
1559};
1560
1561const struct cdevsw ace_cdevsw = {
1562	aceopen, aceclose, aceread, acewrite, aceioctl,
1563	nostop, notty, nopoll, nommap, nokqfilter, D_DISK
1564};
1565
1566void  acegetdefaultlabel(struct ace_softc *, struct disklabel *);
1567void  acegetdisklabel(struct ace_softc *);
1568void  acestart(void *);
1569void  __acestart(struct ace_softc*, struct buf *);
1570void  acerestart(void *);
1571
1572struct dkdriver acedkdriver = { acestrategy, minphys };
1573
1574#ifdef HAS_BAD144_HANDLING
1575static void bad144intern(struct ace_softc *);
1576#endif
1577
1578void
1579aceattach(struct ace_softc *ace)
1580{
1581	struct device *self = ace->sc_dev;
1582	char tbuf[41], pbuf[9], c, *p, *q;
1583	int i, blank;
1584	DEBUG_PRINT(("aceattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
1585
1586	callout_init(&ace->sc_restart_ch, 0);
1587	bufq_alloc(&ace->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
1588
1589	ace->openings = 1; /* wazziz?*/
1590	ace->sc_multi = MAXATATIME;
1591
1592	aprint_naive("\n");
1593
1594	/* setup all required fields so that if the attach fails we are ok */
1595	ace->sc_dk.dk_driver = &acedkdriver;
1596	ace->sc_dk.dk_name = device_xname(ace->sc_dev);
1597
1598	/* read our drive info */
1599	if (sysace_attach(ace) != 0) {
1600		aprint_error_dev(ace->sc_dev, "attach failed\n");
1601		return;
1602	}
1603
1604	aprint_normal_dev(ace->sc_dev, "drive supports %d-sector PIO xfers\n",
1605	    ace->sc_multi);
1606
1607	for (blank = 0, p = ace->sc_params.ModelNumber, q = tbuf, i = 0;
1608	    i < sizeof(ace->sc_params.ModelNumber); i++) {
1609		c = *p++;
1610		if (c == '\0')
1611			break;
1612		if (c != ' ') {
1613			if (blank) {
1614				*q++ = ' ';
1615				blank = 0;
1616			}
1617			*q++ = c;
1618		} else
1619			blank = 1;
1620	}
1621	*q++ = '\0';
1622
1623	aprint_normal_dev(ace->sc_dev, "card is <%s>\n", tbuf);
1624
1625	format_bytes(pbuf, sizeof(pbuf), ace->sc_capacity * DEV_BSIZE);
1626	aprint_normal("%s: %s, %d cyl, %d head, %d sec, "
1627	    "%d bytes/sect x %llu sectors\n",
1628	    self->dv_xname, pbuf,
1629	    (int)(ace->sc_capacity /
1630	    (ace->sc_params.CurrentNumberOfHeads *
1631	    ace->sc_params.CurrentSectorsPerTrack)),
1632	    ace->sc_params.CurrentNumberOfHeads,
1633	    ace->sc_params.CurrentSectorsPerTrack,
1634	    DEV_BSIZE, (unsigned long long)ace->sc_capacity);
1635
1636	/*
1637	 * Attach the disk structure. We fill in dk_info later.
1638	 */
1639	disk_attach(&ace->sc_dk);
1640
1641	rnd_attach_source(&ace->rnd_source, device_xname(ace->sc_dev),
1642			  RND_TYPE_DISK, 0);
1643
1644}
1645
1646int
1647aceactivate(struct device *self, enum devact act)
1648{
1649	int rv = 0;
1650
1651	switch (act) {
1652	case DVACT_DEACTIVATE:
1653		/*
1654		 * Nothing to do; we key off the device's DVF_ACTIVATE.
1655		 */
1656		break;
1657	default:
1658		rv = EOPNOTSUPP;
1659	}
1660	return rv;
1661}
1662
1663int
1664acedetach(struct device *self, int flags)
1665{
1666	struct ace_softc *sc = device_private(self);
1667	int s, bmaj, cmaj, i, mn;
1668
1669	/* locate the major number */
1670	bmaj = bdevsw_lookup_major(&ace_bdevsw);
1671	cmaj = cdevsw_lookup_major(&ace_cdevsw);
1672
1673	/* Nuke the vnodes for any open instances. */
1674	for (i = 0; i < MAXPARTITIONS; i++) {
1675		mn = ACEMINOR(device_unit(self), i);
1676		vdevgone(bmaj, mn, mn, VBLK);
1677		vdevgone(cmaj, mn, mn, VCHR);
1678	}
1679
1680	/* Delete all of our wedges. */
1681	dkwedge_delall(&sc->sc_dk);
1682
1683	s = splbio();
1684
1685	/* Kill off any queued buffers. */
1686	bufq_drain(sc->sc_q);
1687
1688	bufq_free(sc->sc_q);
1689#if 0
1690	sc->atabus->ata_killpending(sc->drvp);
1691#endif
1692
1693	splx(s);
1694
1695	/* Detach disk. */
1696	disk_detach(&sc->sc_dk);
1697
1698	/* Unhook the entropy source. */
1699	rnd_detach_source(&sc->rnd_source);
1700
1701#if 0
1702	sc->drvp->drive_flags = 0; /* no drive any more here */
1703#endif
1704
1705	return 0;
1706}
1707
1708/*
1709 * Read/write routine for a buffer.  Validates the arguments and schedules the
1710 * transfer.  Does not wait for the transfer to complete.
1711 */
1712void
1713acestrategy(struct buf *bp)
1714{
1715	struct ace_softc *ace;
1716	struct disklabel *lp;
1717	daddr_t blkno;
1718	int s;
1719
1720	ace = device_lookup_private(&ace_cd, ACEUNIT(bp->b_dev));
1721
1722	if (ace == NULL) {
1723		bp->b_error = ENXIO;
1724		biodone(bp);
1725		return;
1726	}
1727	lp = ace->sc_dk.dk_label;
1728
1729	DEBUG_PRINT(("acestrategy (%s) %lld\n",
1730	    device_xname(ace->sc_dev), bp->b_blkno), DEBUG_XFERS);
1731
1732	/* Valid request?  */
1733	if (bp->b_blkno < 0 ||
1734	    (bp->b_bcount % lp->d_secsize) != 0 ||
1735	    (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
1736		bp->b_error = EINVAL;
1737		goto done;
1738	}
1739
1740	/* If device invalidated (e.g. media change, door open), error. */
1741	if ((ace->sc_flags & ACEF_LOADED) == 0) {
1742		bp->b_error = EIO;
1743		goto done;
1744	}
1745
1746	/* If it's a null transfer, return immediately. */
1747	if (bp->b_bcount == 0)
1748		goto done;
1749
1750	/*
1751	 * Do bounds checking, adjust transfer. if error, process.
1752	 * If end of partition, just return.
1753	 */
1754	if (ACEPART(bp->b_dev) == RAW_PART) {
1755		if (bounds_check_with_mediasize(bp, DEV_BSIZE,
1756		    ace->sc_capacity) <= 0)
1757			goto done;
1758	} else {
1759		if (bounds_check_with_label(&ace->sc_dk, bp,
1760		    (ace->sc_flags & (ACEF_WLABEL|ACEF_LABELLING)) != 0) <= 0)
1761			goto done;
1762	}
1763
1764	/*
1765	 * Now convert the block number to absolute and put it in
1766	 * terms of the device's logical block size.
1767	 */
1768	if (lp->d_secsize >= DEV_BSIZE)
1769		blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
1770	else
1771		blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
1772
1773	if (ACEPART(bp->b_dev) != RAW_PART)
1774		blkno += lp->d_partitions[ACEPART(bp->b_dev)].p_offset;
1775
1776	bp->b_rawblkno = blkno;
1777
1778	/* Queue transfer on drive, activate drive and controller if idle. */
1779	s = splbio();
1780	bufq_put(ace->sc_q, bp);
1781	acestart(ace);
1782	splx(s);
1783	return;
1784done:
1785	/* Toss transfer; we're done early. */
1786	bp->b_resid = bp->b_bcount;
1787	biodone(bp);
1788}
1789
1790/*
1791 * Queue a drive for I/O.
1792 */
1793void
1794acestart(void *arg)
1795{
1796	struct ace_softc *ace = arg;
1797	struct buf *bp = NULL;
1798
1799	DEBUG_PRINT(("acestart %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS);
1800	while (ace->openings > 0) {
1801
1802		/* Is there a buf for us ? */
1803		if ((bp = bufq_get(ace->sc_q)) == NULL)
1804			return;
1805
1806		/*
1807		 * Make the command. First lock the device
1808		 */
1809		ace->openings--;
1810
1811		ace->retries = 0;
1812		__acestart(ace, bp);
1813	}
1814}
1815
1816void
1817__acestart(struct ace_softc *sc, struct buf *bp)
1818{
1819
1820	sc->sc_bp = bp;
1821	/*
1822	 * If we're retrying, retry in single-sector mode. This will give us
1823	 * the sector number of the problem, and will eventually allow the
1824	 * transfer to succeed.
1825	 */
1826	if (sc->retries >= ACEIORETRIES_SINGLE)
1827		sc->sc_bio.flags = ATA_SINGLE;
1828	else
1829		sc->sc_bio.flags = 0;
1830	if (bp->b_flags & B_READ)
1831		sc->sc_bio.flags |= ATA_READ;
1832	sc->sc_bio.blkno = bp->b_rawblkno;
1833	sc->sc_bio.blkdone = 0;
1834	sc->sc_bio.nbytes = bp->b_bcount;
1835	sc->sc_bio.nblks  = bp->b_bcount >> CF_SECBITS;
1836	sc->sc_bio.databuf = bp->b_data;
1837	/* Instrumentation. */
1838	disk_busy(&sc->sc_dk);
1839	sc->active_xfer = bp;
1840	wakeup(&sc->ch_thread);
1841}
1842
1843void
1844acedone(struct ace_softc *ace)
1845{
1846	struct buf *bp = ace->sc_bp;
1847	const char *errmsg;
1848	int do_perror = 0;
1849
1850	DEBUG_PRINT(("acedone %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS);
1851
1852	if (bp == NULL)
1853		return;
1854
1855	bp->b_resid = ace->sc_bio.nbytes;
1856	switch (ace->sc_bio.error) {
1857	case ETIMEDOUT:
1858		errmsg = "device timeout";
1859	do_perror = 1;
1860		goto retry;
1861	case EBUSY:
1862	case EDOOFUS:
1863		errmsg = "device stuck";
1864retry:		/* Just reset and retry. Can we do more ? */
1865		sysace_reset(ace);
1866		diskerr(bp, "ace", errmsg, LOG_PRINTF,
1867		    ace->sc_bio.blkdone, ace->sc_dk.dk_label);
1868		if (ace->retries < ACEIORETRIES)
1869			printf(", retrying");
1870		printf("\n");
1871		if (do_perror)
1872			aceperror(ace);
1873		if (ace->retries < ACEIORETRIES) {
1874			ace->retries++;
1875			callout_reset(&ace->sc_restart_ch, RECOVERYTIME,
1876			    acerestart, ace);
1877			return;
1878		}
1879
1880		bp->b_error = EIO;
1881		break;
1882	case 0:
1883		if ((ace->sc_bio.flags & ATA_CORR) || ace->retries > 0)
1884			printf("%s: soft error (corrected)\n",
1885			    device_xname(ace->sc_dev));
1886		break;
1887	case ENODEV:
1888	case E2BIG:
1889		bp->b_error = EIO;
1890		break;
1891	}
1892	disk_unbusy(&ace->sc_dk, (bp->b_bcount - bp->b_resid),
1893	    (bp->b_flags & B_READ));
1894	rnd_add_uint32(&ace->rnd_source, bp->b_blkno);
1895	biodone(bp);
1896	ace->openings++;
1897	acestart(ace);
1898}
1899
1900void
1901acerestart(void *v)
1902{
1903	struct ace_softc *ace = v;
1904	struct buf *bp = ace->sc_bp;
1905	int s;
1906	DEBUG_PRINT(("acerestart %s\n",
1907	    device_xname(ace->sc_dev)), DEBUG_XFERS);
1908
1909	s = splbio();
1910	__acestart(v, bp);
1911	splx(s);
1912}
1913
1914int
1915aceread(dev_t dev, struct uio *uio, int flags)
1916{
1917	int r;
1918
1919	DEBUG_PRINT(("aceread\n"), DEBUG_XFERS);
1920	r = physio(acestrategy, NULL, dev, B_READ, minphys, uio);
1921	DEBUG_PRINT(("aceread -> x%x resid=%x\n",r,uio->uio_resid),DEBUG_XFERS);
1922
1923	return r;
1924}
1925
1926int
1927acewrite(dev_t dev, struct uio *uio, int flags)
1928{
1929
1930	DEBUG_PRINT(("acewrite\n"), DEBUG_XFERS);
1931	return physio(acestrategy, NULL, dev, B_WRITE, minphys, uio);
1932}
1933
1934int
1935aceopen(dev_t dev, int flag, int fmt, struct lwp *l)
1936{
1937	struct ace_softc *ace;
1938	int part, error;
1939
1940	DEBUG_PRINT(("aceopen\n"), DEBUG_FUNCS);
1941	ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
1942	if (ace == NULL)
1943		return ENXIO;
1944
1945	if (! device_is_active(ace->sc_dev))
1946		return ENODEV;
1947
1948	part = ACEPART(dev);
1949
1950	mutex_enter(&ace->sc_dk.dk_openlock);
1951
1952	/*
1953	 * If there are wedges, and this is not RAW_PART, then we
1954	 * need to fail.
1955	 */
1956	if (ace->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
1957		error = EBUSY;
1958		goto bad;
1959	}
1960
1961	if (ace->sc_dk.dk_openmask != 0) {
1962		/*
1963		 * If any partition is open, but the disk has been invalidated,
1964		 * disallow further opens.
1965		 */
1966		if ((ace->sc_flags & ACEF_LOADED) == 0) {
1967			error = EIO;
1968			goto bad;
1969		}
1970	} else {
1971		if ((ace->sc_flags & ACEF_LOADED) == 0) {
1972			ace->sc_flags |= ACEF_LOADED;
1973
1974			/* Load the physical device parameters. */
1975			if (ace->sc_capacity == 0) {
1976				error = sysace_identify(ace);
1977				if (error)
1978					goto bad;
1979			}
1980
1981			/* Load the partition info if not already loaded. */
1982			acegetdisklabel(ace);
1983		}
1984	}
1985
1986	/* Check that the partition exists. */
1987	if (part != RAW_PART &&
1988	    (part >= ace->sc_dk.dk_label->d_npartitions ||
1989	     ace->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
1990		error = ENXIO;
1991		goto bad;
1992	}
1993
1994	/* Insure only one open at a time. */
1995	switch (fmt) {
1996	case S_IFCHR:
1997		ace->sc_dk.dk_copenmask |= (1 << part);
1998		break;
1999	case S_IFBLK:
2000		ace->sc_dk.dk_bopenmask |= (1 << part);
2001		break;
2002	}
2003	ace->sc_dk.dk_openmask =
2004	    ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask;
2005
2006	mutex_exit(&ace->sc_dk.dk_openlock);
2007	return 0;
2008
2009 bad:
2010	mutex_exit(&ace->sc_dk.dk_openlock);
2011	return error;
2012}
2013
2014int
2015aceclose(dev_t dev, int flag, int fmt, struct lwp *l)
2016{
2017	struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
2018	int part = ACEPART(dev);
2019
2020	DEBUG_PRINT(("aceclose\n"), DEBUG_FUNCS);
2021	if (ace == NULL)
2022		return ENXIO;
2023
2024	mutex_enter(&ace->sc_dk.dk_openlock);
2025
2026	switch (fmt) {
2027	case S_IFCHR:
2028		ace->sc_dk.dk_copenmask &= ~(1 << part);
2029		break;
2030	case S_IFBLK:
2031		ace->sc_dk.dk_bopenmask &= ~(1 << part);
2032		break;
2033	}
2034	ace->sc_dk.dk_openmask =
2035	    ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask;
2036
2037	if (ace->sc_dk.dk_openmask == 0) {
2038
2039		if (!(ace->sc_flags & ACEF_KLABEL))
2040			ace->sc_flags &= ~ACEF_LOADED;
2041
2042	}
2043
2044	mutex_exit(&ace->sc_dk.dk_openlock);
2045	return 0;
2046}
2047
2048void
2049acegetdefaultlabel(struct ace_softc *ace, struct disklabel *lp)
2050{
2051
2052	DEBUG_PRINT(("acegetdefaultlabel\n"), DEBUG_FUNCS);
2053	memset(lp, 0, sizeof(struct disklabel));
2054
2055	lp->d_secsize = DEV_BSIZE;
2056	lp->d_ntracks = ace->sc_params.CurrentNumberOfHeads;
2057	lp->d_nsectors = ace->sc_params.CurrentSectorsPerTrack;
2058	lp->d_ncylinders = ace->sc_capacity /
2059	    (ace->sc_params.CurrentNumberOfHeads *
2060	     ace->sc_params.CurrentSectorsPerTrack);
2061	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
2062
2063	lp->d_type = DTYPE_ST506; /* ?!? */
2064
2065	strncpy(lp->d_typename, ace->sc_params.ModelNumber, 16);
2066	strncpy(lp->d_packname, "fictitious", 16);
2067	if (ace->sc_capacity > UINT32_MAX)
2068		lp->d_secperunit = UINT32_MAX;
2069	else
2070		lp->d_secperunit = ace->sc_capacity;
2071	lp->d_rpm = 3600;
2072	lp->d_interleave = 1;
2073	lp->d_flags = 0;
2074
2075	lp->d_partitions[RAW_PART].p_offset = 0;
2076	lp->d_partitions[RAW_PART].p_size =
2077	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
2078	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
2079	lp->d_npartitions = RAW_PART + 1;
2080
2081	lp->d_magic = DISKMAGIC;
2082	lp->d_magic2 = DISKMAGIC;
2083	lp->d_checksum = dkcksum(lp);
2084}
2085
2086/*
2087 * Fabricate a default disk label, and try to read the correct one.
2088 */
2089void
2090acegetdisklabel(struct ace_softc *ace)
2091{
2092	struct disklabel *lp = ace->sc_dk.dk_label;
2093	const char *errstring;
2094
2095	DEBUG_PRINT(("acegetdisklabel\n"), DEBUG_FUNCS);
2096
2097	memset(ace->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
2098
2099	acegetdefaultlabel(ace, lp);
2100
2101#ifdef HAS_BAD144_HANDLING
2102	ace->sc_bio.badsect[0] = -1;
2103#endif
2104
2105	errstring = readdisklabel(MAKEACEDEV(0, device_unit(ace->sc_dev),
2106				  RAW_PART), acestrategy, lp,
2107				  ace->sc_dk.dk_cpulabel);
2108	if (errstring) {
2109		printf("%s: %s\n", device_xname(ace->sc_dev), errstring);
2110		return;
2111	}
2112
2113#if DEBUG
2114	if (ACE_DEBUG(DEBUG_WRITES)) {
2115		int i, n = ace->sc_dk.dk_label->d_npartitions;
2116		printf("%s: %d parts\n", device_xname(ace->sc_dev), n);
2117		for (i = 0; i < n; i++) {
2118			printf("\t[%d]: t=%x s=%d o=%d\n", i,
2119			    ace->sc_dk.dk_label->d_partitions[i].p_fstype,
2120			    ace->sc_dk.dk_label->d_partitions[i].p_size,
2121			    ace->sc_dk.dk_label->d_partitions[i].p_offset);
2122		}
2123	}
2124#endif
2125
2126#ifdef HAS_BAD144_HANDLING
2127	if ((lp->d_flags & D_BADSECT) != 0)
2128		bad144intern(ace);
2129#endif
2130}
2131
2132void
2133aceperror(const struct ace_softc *ace)
2134{
2135	const char *devname = device_xname(ace->sc_dev);
2136	uint32_t Status = ace->sc_bio.r_error;
2137
2138	printf("%s: (", devname);
2139
2140	if (Status == 0)
2141		printf("error not notified");
2142	else
2143		printf("status=x%x", Status);
2144
2145	printf(")\n");
2146}
2147
2148int
2149aceioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
2150{
2151	struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
2152	int error = 0, s;
2153
2154	DEBUG_PRINT(("aceioctl\n"), DEBUG_FUNCS);
2155
2156	if ((ace->sc_flags & ACEF_LOADED) == 0)
2157		return EIO;
2158
2159	error = disk_ioctl(&ace->sc_dk, xfer, addr, flag, l);
2160	if (error != EPASSTHROUGH)
2161		return error;
2162
2163	switch (xfer) {
2164#ifdef HAS_BAD144_HANDLING
2165	case DIOCSBAD:
2166		if ((flag & FWRITE) == 0)
2167			return EBADF;
2168		ace->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
2169		ace->sc_dk.dk_label->d_flags |= D_BADSECT;
2170		bad144intern(ace);
2171		return 0;
2172#endif
2173	case DIOCGDINFO:
2174		*(struct disklabel *)addr = *(ace->sc_dk.dk_label);
2175		return 0;
2176
2177	case DIOCGPART:
2178		((struct partinfo *)addr)->disklab = ace->sc_dk.dk_label;
2179		((struct partinfo *)addr)->part =
2180		    &ace->sc_dk.dk_label->d_partitions[ACEPART(dev)];
2181		return 0;
2182
2183	case DIOCWDINFO:
2184	case DIOCSDINFO:
2185	{
2186		struct disklabel *lp;
2187
2188		if ((flag & FWRITE) == 0)
2189			return EBADF;
2190
2191		lp = (struct disklabel *)addr;
2192
2193		mutex_enter(&ace->sc_dk.dk_openlock);
2194		ace->sc_flags |= ACEF_LABELLING;
2195
2196		error = setdisklabel(ace->sc_dk.dk_label,
2197		    lp, /*ace->sc_dk.dk_openmask : */0,
2198		    ace->sc_dk.dk_cpulabel);
2199		if (error == 0) {
2200			if (xfer == DIOCWDINFO)
2201				error = writedisklabel(ACELABELDEV(dev),
2202				    acestrategy, ace->sc_dk.dk_label,
2203				    ace->sc_dk.dk_cpulabel);
2204		}
2205
2206		ace->sc_flags &= ~ACEF_LABELLING;
2207		mutex_exit(&ace->sc_dk.dk_openlock);
2208		return error;
2209	}
2210
2211	case DIOCKLABEL:
2212		if (*(int *)addr)
2213			ace->sc_flags |= ACEF_KLABEL;
2214		else
2215			ace->sc_flags &= ~ACEF_KLABEL;
2216		return 0;
2217
2218	case DIOCWLABEL:
2219		if ((flag & FWRITE) == 0)
2220			return EBADF;
2221		if (*(int *)addr)
2222			ace->sc_flags |= ACEF_WLABEL;
2223		else
2224			ace->sc_flags &= ~ACEF_WLABEL;
2225		return 0;
2226
2227	case DIOCGDEFLABEL:
2228		acegetdefaultlabel(ace, (struct disklabel *)addr);
2229		return 0;
2230
2231	case DIOCCACHESYNC:
2232		return 0;
2233
2234	case DIOCAWEDGE:
2235	    {
2236		struct dkwedge_info *dkw = (void *) addr;
2237
2238		if ((flag & FWRITE) == 0)
2239			return EBADF;
2240
2241		/* If the ioctl happens here, the parent is us. */
2242		strcpy(dkw->dkw_parent, device_xname(ace->sc_dev));
2243		return dkwedge_add(dkw);
2244	    }
2245
2246	case DIOCDWEDGE:
2247	    {
2248		struct dkwedge_info *dkw = (void *) addr;
2249
2250		if ((flag & FWRITE) == 0)
2251			return EBADF;
2252
2253		/* If the ioctl happens here, the parent is us. */
2254		strcpy(dkw->dkw_parent, device_xname(ace->sc_dev));
2255		return dkwedge_del(dkw);
2256	    }
2257
2258	case DIOCLWEDGES:
2259	    {
2260		struct dkwedge_list *dkwl = (void *) addr;
2261
2262		return dkwedge_list(&ace->sc_dk, dkwl, l);
2263	    }
2264
2265	case DIOCGSTRATEGY:
2266	    {
2267		struct disk_strategy *dks = (void *)addr;
2268
2269		s = splbio();
2270		strlcpy(dks->dks_name, bufq_getstrategyname(ace->sc_q),
2271		    sizeof(dks->dks_name));
2272		splx(s);
2273		dks->dks_paramlen = 0;
2274
2275		return 0;
2276	    }
2277
2278	case DIOCSSTRATEGY:
2279	    {
2280		struct disk_strategy *dks = (void *)addr;
2281		struct bufq_state *new;
2282		struct bufq_state *old;
2283
2284		if ((flag & FWRITE) == 0) {
2285			return EBADF;
2286		}
2287		if (dks->dks_param != NULL) {
2288			return EINVAL;
2289		}
2290		dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
2291		error = bufq_alloc(&new, dks->dks_name,
2292		    BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
2293		if (error) {
2294			return error;
2295		}
2296		s = splbio();
2297		old = ace->sc_q;
2298		bufq_move(new, old);
2299		ace->sc_q = new;
2300		splx(s);
2301		bufq_free(old);
2302
2303		return 0;
2304	    }
2305
2306#ifdef USE_ACE_FOR_RECONFIG
2307	/*
2308	 * Ok, how do I get this standardized
2309	 * [nothing to do with disks either]
2310	 */
2311#define DIOC_FPGA_RECONFIGURE _IOW('d',166, struct ioctl_pt)
2312	case DIOC_FPGA_RECONFIGURE:
2313	    {
2314		/*
2315		 * BUGBUG This is totally wrong, we need to fault in
2316		 * all data in advance.
2317		 * Otherwise we get back here with the sysace in a bad state
2318		 * (its NOT reentrant!)
2319		 */
2320		struct ioctl_pt *pt = (struct ioctl_pt *)addr;
2321		return sysace_send_config(ace,(uint32_t*)pt->data,pt->com);
2322	    }
2323#endif /* USE_ACE_FOR_RECONFIG */
2324
2325	default:
2326		/*
2327		 * NB: we get a DIOCGWEDGEINFO, but nobody else handles it
2328		 * either
2329		 */
2330		DEBUG_PRINT(("aceioctl: unsup x%lx\n", xfer), DEBUG_FUNCS);
2331		return ENOTTY;
2332	}
2333}
2334
2335int
2336acesize(dev_t dev)
2337{
2338	struct ace_softc *ace;
2339	int part, omask;
2340	int size;
2341
2342	DEBUG_PRINT(("acesize\n"), DEBUG_FUNCS);
2343
2344	ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
2345	if (ace == NULL)
2346		return -1;
2347
2348	part = ACEPART(dev);
2349	omask = ace->sc_dk.dk_openmask & (1 << part);
2350
2351	if (omask == 0 && aceopen(dev, 0, S_IFBLK, NULL) != 0)
2352		return -1;
2353	if (ace->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
2354		size = -1;
2355	else
2356		size = ace->sc_dk.dk_label->d_partitions[part].p_size *
2357		    (ace->sc_dk.dk_label->d_secsize / DEV_BSIZE);
2358	if (omask == 0 && aceclose(dev, 0, S_IFBLK, NULL) != 0)
2359		return -1;
2360	return size;
2361}
2362
2363/* #define ACE_DUMP_NOT_TRUSTED if you just want to watch */
2364#define ACE_DUMP_NOT_TRUSTED
2365static int acedoingadump = 0;
2366
2367/*
2368 * Dump core after a system crash.
2369 */
2370int
2371acedump(dev_t dev, daddr_t blkno, void *va, size_t size)
2372{
2373	struct ace_softc *ace;	/* disk unit to do the I/O */
2374	struct disklabel *lp;   /* disk's disklabel */
2375	int part, err;
2376	int nblks;	/* total number of sectors left to write */
2377
2378	/* Check if recursive dump; if so, punt. */
2379	if (acedoingadump)
2380		return EFAULT;
2381	acedoingadump = 1;
2382
2383	ace = device_lookup_private(&ace_cd, ACEUNIT(dev));
2384	if (ace == NULL)
2385		return ENXIO;
2386
2387	part = ACEPART(dev);
2388
2389	/* Convert to disk sectors.  Request must be a multiple of size. */
2390	lp = ace->sc_dk.dk_label;
2391	if ((size % lp->d_secsize) != 0)
2392		return EFAULT;
2393	nblks = size / lp->d_secsize;
2394	blkno = blkno / (lp->d_secsize / DEV_BSIZE);
2395
2396	/* Check transfer bounds against partition size. */
2397	if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
2398		return EINVAL;
2399
2400	/* Offset block number to start of partition. */
2401	blkno += lp->d_partitions[part].p_offset;
2402
2403	ace->sc_bp = NULL;
2404	ace->sc_bio.blkno = blkno;
2405	ace->sc_bio.flags = ATA_POLL;
2406	ace->sc_bio.nbytes = nblks * lp->d_secsize;
2407	ace->sc_bio.databuf = va;
2408#ifndef ACE_DUMP_NOT_TRUSTED
2409	ace->active_xfer = bp;
2410	wakeup(&ace->ch_thread);
2411
2412	switch(ace->sc_bio.error) {
2413	case ETIMEDOUT:
2414		printf("acedump: device timed out");
2415		err = EIO;
2416		break;
2417	case 0:
2418		err = 0;
2419		break;
2420	default:
2421		panic("acedump: unknown error type");
2422	}
2423	if (err != 0) {
2424		printf("\n");
2425		return err;
2426	}
2427#else	/* ACE_DUMP_NOT_TRUSTED */
2428	/* Let's just talk about this first... */
2429	device_printf(ace->sc_dev, ": dump addr 0x%p, size %zu blkno %llx\n",
2430	    va, size, blkno);
2431	DELAY(500 * 1000);	/* half a second */
2432	err = 0;
2433#endif
2434
2435	acedoingadump = 0;
2436	return 0;
2437}
2438
2439#ifdef HAS_BAD144_HANDLING
2440/*
2441 * Internalize the bad sector table.
2442 */
2443void
2444bad144intern(struct ace_softc *ace)
2445{
2446	struct dkbad *bt = &ace->sc_dk.dk_cpulabel->bad;
2447	struct disklabel *lp = ace->sc_dk.dk_label;
2448	int i = 0;
2449
2450	DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
2451
2452	for (; i < NBT_BAD; i++) {
2453		if (bt->bt_bad[i].bt_cyl == 0xffff)
2454			break;
2455		ace->sc_bio.badsect[i] =
2456		    bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
2457		    (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
2458		    (bt->bt_bad[i].bt_trksec & 0xff);
2459	}
2460	for (; i < NBT_BAD+1; i++)
2461		ace->sc_bio.badsect[i] = -1;
2462}
2463#endif
2464
2465static void
2466ace_params_to_properties(struct ace_softc *ace)
2467{
2468	prop_dictionary_t disk_info, odisk_info, geom;
2469	const char *cp;
2470
2471	disk_info = prop_dictionary_create();
2472
2473	cp = ST506;
2474
2475	prop_dictionary_set_cstring_nocopy(disk_info, "type", cp);
2476
2477	geom = prop_dictionary_create();
2478
2479	prop_dictionary_set_uint64(geom, "sectors-per-unit", ace->sc_capacity);
2480
2481	prop_dictionary_set_uint32(geom, "sector-size",
2482	    DEV_BSIZE /* XXX 512? */);
2483
2484	prop_dictionary_set_uint16(geom, "sectors-per-track",
2485	    ace->sc_params.CurrentSectorsPerTrack);
2486
2487	prop_dictionary_set_uint16(geom, "tracks-per-cylinder",
2488	    ace->sc_params.CurrentNumberOfHeads);
2489
2490	prop_dictionary_set_uint64(geom, "cylinders-per-unit",
2491	    ace->sc_capacity /
2492	    (ace->sc_params.CurrentNumberOfHeads *
2493	     ace->sc_params.CurrentSectorsPerTrack));
2494
2495	prop_dictionary_set(disk_info, "geometry", geom);
2496	prop_object_release(geom);
2497
2498	prop_dictionary_set(device_properties(ace->sc_dev),
2499	    "disk-info", disk_info);
2500
2501	/*
2502	 * Don't release disk_info here; we keep a reference to it.
2503	 * disk_detach() will release it when we go away.
2504	 */
2505
2506	odisk_info = ace->sc_dk.dk_info;
2507	ace->sc_dk.dk_info = disk_info;
2508	if (odisk_info)
2509		prop_object_release(odisk_info);
2510}
2511