xref: /netbsd-src/sys/arch/emips/stand/common/ace.c (revision 7991f5a7b8fc83a3d55dc2a1767cca3b84103969)
1 /*	$NetBSD: ace.c,v 1.5 2021/07/24 21:31:32 andvar Exp $	*/
2 
3 /*-
4  * Copyright (c) 2010 The NetBSD Foundation, Inc.
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code was written by Alessandro Forin and Neil Pittman
9  * at Microsoft Research and contributed to The NetBSD Foundation
10  * by Microsoft Corporation.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /* --------------------------------------------------------------------------
35  *
36  * Module:
37  *
38  *    ace.c
39  *
40  * Purpose:
41  *
42  *    Driver for the Xilinx System ACE CompactFlash Solution
43  *
44  * Author:
45  *    A. Forin (sandrof)
46  *
47  * References:
48  *    "System ACE CompactFlash Solution", Advance Product Specification
49  *    Document DS080 Version 1.5 April 5, 2002.  Xilinx Corp.
50  *    Available at http://www.xilinx.com
51  *
52  *    "CF+ and CompactFlash Specification", Revision 4.1, 02/16/2007.
53  *    CompactFlash Association.
54  *    Available at http://www.compactflash.org
55  * --------------------------------------------------------------------------
56  */
57 
58 #include <lib/libsa/stand.h>
59 #include <lib/libkern/libkern.h>
60 #include <machine/emipsreg.h>
61 
62 #include <sys/param.h>
63 #include <sys/disklabel.h>
64 #include <sys/endian.h>
65 
66 #include "common.h"
67 #include "ace.h"
68 #include "start.h"
69 
70 #define NSAC 2
71 #define SAC0 ((struct _Sac  *)IDE_DEFAULT_ADDRESS)
72 #define SAC1 ((struct _Sac  *)(IDE_DEFAULT_ADDRESS+256))
73 
74 #define CF_SECBITS     9
75 #define CF_SECTOR_SIZE (1 << CF_SECBITS)
76 
77 
78 /* Error codes
79  */
80 #define FAILED(x)           (x < 0)
81 #define S_OK                (0)
82 #define E_INVALID_PARAMETER (-1)
83 #define E_DISK_RESET_FAILED (-2)
84 #define E_NO_MEDIA_IN_DRIVE (-3)
85 #define E_TIMED_OUT         (-4)
86 
87 /* Utilities
88  */
89 #if defined(DEBUG)
90 int acedebug = 2;
91 #define DBGME(lev,x) \
92 	do \
93 		if (lev >= acedebug) { \
94 			x; \
95 		} \
96 	while (/*CONSTCOND*/0)
97 #else
98 #define DBGME(lev,x)
99 #endif
100 
101 #if defined(DEBUG)
102 typedef char *NAME;
103 typedef struct _REGDESC {
104     NAME RegisterName;
105     NAME BitNames[32];
106 } REGDESC, *PREGDESC;
107 
108 static void SysacePrintRegister(const REGDESC *Desc, uint32_t Value);
109 
SysacePrintRegister(const REGDESC * Desc,uint32_t Value)110 static void SysacePrintRegister(const REGDESC *Desc, uint32_t Value)
111 {
112     int i;
113     printf("\t%s %x =", Desc->RegisterName, Value);
114     for (i = 31; i >= 0; i--) {
115         if (Value & (1 << i))
116             printf(" %s",
117                      (Desc->BitNames[i]) ? Desc->BitNames[i] : "?");
118     }
119     printf("\n");
120 }
121 
SysaceDumpRegisters(struct _Sac * Interface)122 static void SysaceDumpRegisters(struct _Sac *Interface)
123 {
124 	const REGDESC Control_Names =
125         { "Control",
126           {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
127           "RST", //			0x00010000
128           "BUS8", //		0x00020000
129           "BUS16", //		0x00040000
130           "BUS32", //		0x00080000
131           "IRQ", //			0x00100000
132           "BRDY", //		0x00200000
133           "IMSK0", //		0x00400000
134           "IMSK1", //		0x00800000
135           "TD0", //	    	0x0f000000
136           "TD1", //		    0x0f000000
137           "TD2", //	    	0x0f000000
138           "TD3", //	    	0x0f000000
139           "BUFW8", //		0x10000000
140           "BUFW16", //		0x20000000
141           "BUFW32", //		0x40000000
142           "DEBUG"} //		0x80000000
143         };
144 
145 	const REGDESC STATUS_Names =
146         { "STATUS",
147           {"CFGLOCK", //	0x00000001
148           "MPULOCK", //		0x00000002
149           "CFGERROR", //	0x00000004
150           "CFCERROR", //	0x00000008
151           "CFDETECT", //	0x00000010
152           "DATABUFRDY", //	0x00000020
153           "DATABUFWRITE", //0x00000040
154           "CFGDONE", //		0x00000080
155           "RDYFORCFCMD", //	0x00000100
156           "CFGMODEPIN", //	0x00000200
157           0,0,0,
158           "CFGADDRPIN0", //	0x0000e000
159           "CFGADDRPIN1", //	0x0000e000
160           "CFGADDRPIN2", //	0x0000e000
161           0,
162           "CFBSY", //		0x00020000
163           "CFRDY", //		0x00040000
164           "CFDWF", //		0x00080000
165           "CFDSC", //		0x00100000
166           "CFDRQ", //		0x00200000
167           "CFCORR", //		0x00400000
168           "CFERR", //		0x00800000
169           0,}
170         };
171 
172 	const REGDESC ERRORREG_Names =
173         { "ERRORREG",
174           {"CARDRESETERR", //			0x00000001
175           "CARDRDYERR", //				0x00000002
176           "CARDREADERR", //				0x00000004
177           "CARDWRITEERR", //			0x00000008
178           "SECTORRDYERR", //			0x00000010
179           "CFGADDRERR", //				0x00000020
180           "CFGFAILED", //				0x00000040
181           "CFGREADERR", //				0x00000080
182           "CFGINSTRERR", //				0x00000100
183           "CFGINITERR", //				0x00000200
184           0,
185           "CFBBK", //					0x00000800
186           "CFUNC", //					0x00001000
187           "CFIDNF", //					0x00002000
188           "CFABORT", //					0x00004000
189           "CFAMNF", //					0x00008000
190            0,}
191         };
192 
193     const NAME CommandNames[8] =
194         { "0", //     				0x0000
195           "RESETMEMCARD", //   		0x0100
196           "IDENTIFYMEMCARD", //		0x0200
197           "READMEMCARDDATA", //		0x0300
198           "WRITEMEMCARDDATA", //  	0x0400
199           "5", //     				0x0500
200           "ABORT", //			    0x0600
201           "7" //     			    0x0700
202         };
203 
204 	const REGDESC CONTROLREG_Names =
205         { "CONTROLREG",
206           {"FORCELOCKREQ", //			0x00000001
207           "LOCKREQ", //					0x00000002
208           "FORCECFGADDR", //			0x00000004
209           "FORCECFGMODE", //			0x00000008
210           "CFGMODE", //					0x00000010
211           "CFGSTART", //				0x00000020
212           "CFGSEL_MPU", //  			0x00000040
213           "CFGRESET", //				0x00000080
214           "DATABUFRDYIRQ", //			0x00000100
215           "ERRORIRQ", //				0x00000200
216           "CFGDONEIRQ", //				0x00000400
217           "RESETIRQ", //				0x00000800
218           "CFGPROG", //					0x00001000
219           "CFGADDR_B0", //				0x00002000
220           "CFGADDR_B1", //				0x00004000
221           "CFGADDR_B2", //				0x00008000
222           0,}
223         };
224 
225 	const REGDESC FATSTATREG_Names =
226         { "FATSTATREG",
227           {"MBRVALID", //				0x00000001
228           "PBRVALID", //				0x00000002
229           "MBRFAT12", //				0x00000004
230           "PBRFAT12", //				0x00000008
231           "MBRFAT16", //				0x00000010
232           "PBRFAT16", //				0x00000020
233           "CALCFAT12", //				0x00000040
234           "CALCFAT16", //				0x00000080
235           0, }
236         };
237 
238     printf("Sysace@%p:\n", Interface);
239     printf("\tTag %x\n", Interface->Tag);
240     SysacePrintRegister(&Control_Names, Interface->Control);
241     printf("\tBUSMODEREG %x\n", Interface->BUSMODEREG);
242     SysacePrintRegister(&STATUS_Names, Interface->STATUS);
243     SysacePrintRegister(&ERRORREG_Names, Interface->ERRORREG);
244     printf("\tCFGLBAREG %x\n", Interface->CFGLBAREG);
245     printf("\tMPULBAREG %x\n", Interface->MPULBAREG);
246     printf("\tVERSIONREG %x\n", Interface->VERSIONREG);
247     printf("\tSECCNTCMDREG %x = %s cnt=%d\n", Interface->SECCNTCMDREG,
248              CommandNames[(Interface->SECCNTCMDREG >> 8)&7],
249              Interface->SECCNTCMDREG & SAC_SECCCNT);
250     SysacePrintRegister(&CONTROLREG_Names, Interface->CONTROLREG);
251     SysacePrintRegister(&FATSTATREG_Names, Interface->FATSTATREG);
252 }
253 
254 #else
255 #define SysaceDumpRegisters(_c_)
256 #endif
257 
258 /* Reset the device and the interface
259  */
SysaceInitialize(struct _Sac * Interface)260 static int SysaceInitialize(struct _Sac *Interface)
261 {
262     /* 16bit mode etc etc */
263 	uint32_t BusMode, Control;
264 
265     /* reset our interface */
266     Interface->Control = SAC_RST;
267     Delay(200);
268 
269     /* repeat on both byte lanes */
270 	Interface->BUSMODEREG = SAC_MODE16 | (SAC_MODE16 << 8);
271     Delay(1);
272 
273     /* check what our interface does and what the SysACE expects */
274 	Control = Interface->Control;
275 	BusMode = Interface->BUSMODEREG;
276 
277     /* get them to agree */
278 	if (BusMode & SAC_MODE16)
279 	{
280 		Interface->Control = Control | SAC_BUS16;
281 		Interface->Control = Interface->Control & ~SAC_BUS8;
282 	}
283 	else
284 	{
285 		Interface->Control = Control | SAC_BUS8;
286 		Interface->Control = Interface->Control & ~SAC_BUS16;
287 	}
288 
289     /* check that it worked */
290 	BusMode = Interface->BUSMODEREG;
291 	Control = Interface->Control;
292 
293 	if (((BusMode & SAC_MODE16) == 0) && ((Control & SAC_BUS8) == 0)) return E_DISK_RESET_FAILED;
294 	if (((BusMode & SAC_MODE16) > 0) && ((Control & SAC_BUS16) == 0)) return E_DISK_RESET_FAILED;
295 
296     /* interrupts off for now */
297     Interface->Control &= ~SAC_INTMASK;
298 #define SAC_INTERRUPTS (SAC_DATABUFRDYIRQ |	SAC_ERRORIRQ )// | SAC_CFGDONEIRQ)
299     Control = Interface->CONTROLREG;
300     Control = (Control & ~SAC_INTERRUPTS) | SAC_RESETIRQ | SAC_FORCECFGMODE;
301     Interface->CONTROLREG = Control;
302     Interface->CONTROLREG = Control & ~SAC_RESETIRQ;
303 
304     /* no command */
305     Interface->MPULBAREG = 0;
306 
307     return S_OK;
308 }
309 
310 /* Take control of the ACE datapath
311  */
SysaceLock(struct _Sac * Interface)312 static int SysaceLock(struct _Sac *Interface)
313 {
314     uint32_t Status;
315     int i;
316 
317     /* Locked already?
318      */
319     Status = Interface->STATUS;
320     if (Status & SAC_MPULOCK)
321         return TRUE;
322 
323     /* Request lock
324      */
325     Interface->CONTROLREG |= SAC_LOCKREQ;
326 
327     /* Spin a bit until we get it
328      */
329     for (i = 0; i < 200; i++) {
330         Status = Interface->STATUS;
331         if (Status & SAC_MPULOCK)
332             return TRUE;
333         Delay(100);
334         DBGME(0,printf("Sysace::Lock loops.. (st=%x)\n",Status));
335     }
336 
337     /* oopsie!
338      */
339     DBGME(3,printf("Sysace::Lock timeout (st=%x)\n",Status));
340     SysaceDumpRegisters(Interface);
341     return FALSE;
342 }
343 
344 /* Release control of the ACE datapath
345  */
SysaceUnlock(struct _Sac * Interface)346 static int SysaceUnlock(struct _Sac *Interface)
347 {
348     uint32_t Status;
349     int i;
350 
351     /* Clear reset
352      */
353     Interface->CONTROLREG &= ~SAC_CFGRESET;
354 
355     /* Unlocked already?
356      */
357     Status = Interface->STATUS;
358     if (0 == (Status & SAC_MPULOCK))
359         return TRUE;
360 
361     /* Request unlock
362      */
363     Interface->CONTROLREG &= ~SAC_LOCKREQ;
364 
365     /* Spin a bit until we get it
366      */
367     for (i = 0; i < 200; i++) {
368         Status = Interface->STATUS;
369         if (0 == (Status & SAC_MPULOCK))
370             return TRUE;
371         Delay(100);
372         DBGME(0,printf("Sysace::Unlock loops.. (st=%x)\n",Status));
373     }
374 
375     /* oopsie!
376      */
377     DBGME(3,printf("Sysace::Unlock timeout (st=%x)\n",Status));
378     SysaceDumpRegisters(Interface);
379     return FALSE;
380 }
381 
382 /* Check if the ACE is waiting for a comamnd
383  */
384 #define SysaceReadyForCommand(_i_) ((_i_)->STATUS & SAC_RDYFORCFCMD)
385 
386 /* Check if the ACE is executing a comamnd
387  */
388 #define SysaceBusyWithCommand(_i_) ((_i_)->STATUS & SAC_CFBSY)
389 
390 /* Turn on interrupts from the ACE
391  */
392 #define SysaceInton(_i_) { \
393           (_i_)->CONTROLREG |= SAC_INTERRUPTS; \
394           (_i_)->Control |= SAC_INTMASK; \
395 }
396 
397 /* Turn off interrupts from the ACE
398  */
399 #define SysaceIntoff(_i_) { \
400           (_i_)->CONTROLREG &= ~SAC_INTERRUPTS; \
401           (_i_)->Control &= ~SAC_INTMASK; \
402 }
403 
404 /* Start a command on the ACE, such as read or identify.
405  */
SysaceStartCommand(struct _Sac * Interface,uint32_t Command,uint32_t Lba,uint32_t nSectors)406 static int SysaceStartCommand(struct _Sac *Interface,
407                               uint32_t Command,
408                               uint32_t Lba,
409                               uint32_t nSectors)
410 {
411     int sc = E_DISK_RESET_FAILED;
412 
413     /* Lock it if not already
414      */
415     if (!SysaceLock(Interface)) {
416         /* printed already */
417         return sc;
418     }
419 
420     /* Is there a CF inserted
421      */
422     if (! (Interface->STATUS & SAC_CFDETECT)) {
423         /* NB: Not a failure state */
424         DBGME(2,printf("Sysace:: no media (st=%x)\n",Interface->STATUS));
425         return E_NO_MEDIA_IN_DRIVE;
426     }
427 
428     /* Is it ready for a command
429      */
430     if (!SysaceReadyForCommand(Interface)) {
431         DBGME(3,printf("Sysace:: not ready (st=%x)\n",Interface->STATUS));
432         SysaceDumpRegisters(Interface);
433         return sc;
434     }
435 
436     /* sector number and command
437      */
438     Interface->MPULBAREG = Lba;
439     Interface->SECCNTCMDREG = (uint16_t)(Command | (nSectors & SAC_SECCCNT));
440 
441     /* re-route the chip
442      * NB: The word "RESET" is actually not much of a misnomer.
443      * The chip was designed for a one-shot execution only, at reset time,
444      * namely loading the configuration data into the FPGA. So..
445      */
446     Interface->CONTROLREG |= SAC_CFGRESET;
447     return S_OK;
448 }
449 
450 
451 /* "Interrupt service routine"
452  */
SysAce_isr(struct _Sac * Interface)453 static void SysAce_isr ( struct _Sac *Interface )
454 {
455     uint32_t Control;
456 
457     /* Turn off interrupts and ACK them
458      */
459     SysaceIntoff(Interface);
460 
461     Control = Interface->CONTROLREG & (~(SAC_RESETIRQ|SAC_INTERRUPTS));
462     Interface->CONTROLREG = Control | SAC_RESETIRQ;
463     Interface->CONTROLREG = Control;
464 }
465 
SysAce_wait(struct _Sac * Interface)466 static int SysAce_wait(struct _Sac *Interface)
467 {
468     int i;
469     for (i = 0; i < 30000; i++) {
470         if (Interface->STATUS & SAC_DATABUFRDY) {
471             SysAce_isr(Interface);
472             return S_OK;
473         }
474         Delay(100);
475     }
476     return E_TIMED_OUT;
477 }
478 
479 
480 /* Read NBLOCKS blocks of 512 bytes each,
481  * starting at block number STARTSECTOR,
482  * into the buffer BUFFER.
483  * Return 0 if ok, -1 otherwise.
484  */
SysAce_read(struct _Sac * Interface,char * Buffer,uint32_t StartSector,uint32_t nBlocks)485 static int SysAce_read(struct _Sac * Interface, char *Buffer, uint32_t StartSector, uint32_t nBlocks)
486 {
487     int sc = S_OK;
488     uint32_t Size, SizeThisTime;
489     uint32_t Status = 0, SizeRead = 0;
490     unsigned int i, j;
491 
492     Size = nBlocks << CF_SECBITS;
493 
494     DBGME(1,printf("Sysace Read(%p %x %x)\n",
495                      Buffer, StartSector, nBlocks));
496 
497     /* Repeat until we are done or error
498      */
499     while (sc == S_OK) {
500 
501         /* .. one sector at a time
502          * BUGBUG Supposedly we can do up to 256 sectors?
503          */
504         SizeThisTime = Size;
505         if (SizeThisTime > CF_SECTOR_SIZE)
506             SizeThisTime = CF_SECTOR_SIZE;
507 
508         /*  Start a new sector read
509          */
510         SysaceInton(Interface);
511         sc = SysaceStartCommand(Interface,
512                                 SAC_CMD_READMEMCARDDATA,
513                                 StartSector,
514                                 1);
515         /* And wait until done, if ok
516          */
517         if (!FAILED(sc)) {
518             sc = SysAce_wait(Interface);
519         }
520 
521         /* Are we doing ok
522          */
523         if (!FAILED(sc)) {
524 
525             /* Get the data out of the ACE
526              */
527             for (i = 0; i < SizeThisTime; i += 4) {
528 
529                 /* Make sure the FIFO is ready
530                  */
531                 for (j = 0; j < 100; j++) {
532                     Status = Interface->STATUS;
533                     if (Status & SAC_DATABUFRDY)
534                         break;
535                     Delay(10);
536                 }
537 
538                 /* Got it?
539                  */
540                 if (Status & SAC_DATABUFRDY) {
541                     uint32_t Data32;
542 
543                     Data32 = Interface->DATABUFREG[0];
544                     Data32 = le32toh(Data32);
545 		    DBGME(0,printf(" %x", Data32));
546 		    if (0 == (0xf & (i+4))) DBGME(0,printf("\n"));
547                     memcpy(Buffer+i, &Data32, 4);
548                 }
549                 else
550                 {
551                     /* Ooops, get out of here
552                      */
553                     DBGME(3,printf("Sysace::READ timeout\n"));
554                     SysaceDumpRegisters(Interface);
555                     sc = E_TIMED_OUT;
556                     break;
557                 }
558             }
559 
560             /* Still doing ok?
561              */
562             if (!FAILED(sc)) {
563                 StartSector        += 1;
564                 Buffer             += SizeThisTime;
565                 SizeRead           += SizeThisTime;
566                 Size               -= SizeThisTime;
567             }
568         }
569 
570         /* Free the ACE for the JTAG, just in case */
571         SysaceUnlock(Interface);
572 
573         /* Are we done yet?
574          */
575         if (Size == 0)
576             break;
577     }
578 
579     return sc;
580 }
581 
582 /* Exported interface
583  */
584 struct	ace_softc {
585     struct _Sac *sc_dp;         /* I/O regs */
586 	int	sc_part;		        /* disk partition number */
587 	struct	disklabel sc_label;	/* disk label for this disk */
588 };
589 
590 #define	RF_PROTECTED_SECTORS	64	/* XXX refer to <.../rf_optnames.h> */
591 
aceprobe(int unit)592 int aceprobe(int unit)
593 {
594     struct _Sac *Sac;
595 
596     if (unit == 0)
597         Sac = SAC0;
598     else if (unit == 1)
599         Sac = SAC1;
600     else
601         return E_INVALID_PARAMETER;
602 
603     /* Check the tag to see if its there
604      */
605     if ((Sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE) {
606         DBGME(3,printf("init_ace: bad tag (%x != %x) @x%p\n",
607                        Sac->Tag, PMTTAG_SYSTEM_ACE, Sac));
608         return E_INVALID_PARAMETER;
609     }
610 
611     return S_OK;
612 }
613 
614 /* aceopen("", ctlr, unit, part);
615  */
616 int
aceopen(struct open_file * f,...)617 aceopen(struct open_file *f, ...)
618 {
619 	int ctlr, unit, part;
620     struct _Sac *Sac;
621 
622 	struct ace_softc *sc;
623 	struct disklabel *lp;
624 	int i;
625 	char *msg;
626 	char buf[DEV_BSIZE];
627 	size_t cnt;
628 	va_list ap;
629 
630 	va_start(ap, f);
631 
632 	ctlr = va_arg(ap, int);
633 	unit = va_arg(ap, int);
634 	part = va_arg(ap, int);
635 	va_end(ap);
636 
637 	if (ctlr != 0 || unit >= NSAC || part >= 8)
638 		return (ENXIO);
639 
640     /* Is it there, does it work.
641      */
642     Sac = (unit == 0) ? SAC0 : SAC1;
643     i = aceprobe(unit);
644 	if (i < 0)
645         goto Bad;
646 
647     if (SysaceInitialize(Sac) < 0) {
648         DBGME(3,printf("ace%d: no reset @x%p\n", unit, Sac));
649     Bad:
650 		printf("open failed\n");
651 		return (ENXIO);
652     }
653 
654     /* Yep, go ahead.
655      */
656 	sc = alloc(sizeof(struct ace_softc));
657 	memset(sc, 0, sizeof(struct ace_softc));
658 	f->f_devdata = (void *)sc;
659 
660 	sc->sc_dp = Sac;
661 	sc->sc_part = part;
662 
663 	/* try to read disk label and partition table information */
664 	lp = &sc->sc_label;
665 	lp->d_secsize = DEV_BSIZE;
666 	lp->d_secpercyl = 1;
667 	lp->d_npartitions = MAXPARTITIONS;
668 	lp->d_partitions[part].p_offset = 0;
669 	lp->d_partitions[part].p_size = 0x7fffffff;
670 
671 	i = acestrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt);
672 	if (i || cnt != DEV_BSIZE) {
673 		DBGME(3,printf("ace%d: error reading disk label\n", unit));
674 		goto bad;
675 	}
676 	msg = getdisklabel(buf, lp);
677 	if (msg) {
678 		/* If no label, just assume 0 and return */
679 		return (0);
680 	}
681 
682 	if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
683 	bad:
684 		dealloc(sc, sizeof(struct ace_softc));
685 		DBGME(3,printf("ace%d: bad part %d\n", unit, part));
686 		return (ENXIO);
687 	}
688 	return (0);
689 }
690 
691 #ifndef LIBSA_NO_DEV_CLOSE
692 int
aceclose(struct open_file * f)693 aceclose(struct open_file *f)
694 {
695 	dealloc(f->f_devdata, sizeof(struct ace_softc));
696 	f->f_devdata = (void *)0;
697 	return (0);
698 }
699 #endif
700 
701 int
acestrategy(void * devdata,int rw,daddr_t bn,size_t reqcnt,void * addr,size_t * cnt)702 acestrategy(
703 	void *devdata,
704 	int rw,
705 	daddr_t bn,
706 	size_t reqcnt,
707 	void *addr,
708 	size_t *cnt)	/* out: number of bytes transferred */
709 {
710 	struct ace_softc *sc = (struct ace_softc *)devdata;
711 	int part = sc->sc_part;
712 	struct partition *pp = &sc->sc_label.d_partitions[part];
713 	int s;
714 	uint32_t sector;
715 
716 #if 0 //useless?
717     if (rw != F_READ)
718         return (EINVAL);
719 #endif
720 
721 	/*
722 	 * Partial-block transfers not handled.
723 	 */
724 	if (reqcnt & (DEV_BSIZE - 1)) {
725 		*cnt = 0;
726 		return (EINVAL);
727 	}
728 
729     /*
730      * Compute starting sector
731      */
732 	sector = bn;
733 	sector += pp->p_offset;
734 	if (pp->p_fstype == FS_RAID)
735 		sector += RF_PROTECTED_SECTORS;
736 
737     /* read */
738     s = SysAce_read(sc->sc_dp,addr,sector,reqcnt >> CF_SECBITS);
739 
740 	if (s < 0)
741 		return (EIO);
742 
743     /* BUGBUG there's no validation we don't fall off the deep end */
744 	*cnt = reqcnt;
745 	return (0);
746 }
747 
748