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