1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  M-Systems Block Device Driver for
5    *  Binary Partition region of DiskOnChip (TM) Devices
6    *  File: dev_msys.c
7    *
8    *  To create a binary partition, we use the M-Systems Linux utility
9    *  "dformat" for low-level (INFTL/NFTL) format the device for a
10    *  BDTL (Block Device translation Layer) Partition as well as a
11    *  user-defined binary partition of various sizes. Hereis an
12    *  example of creating a device with a name of BIPO of size 1M with
13    *  initial 800K kernel data image file vmlinux.img
14    *
15    *  dformat -win:1f006000 -bdkL0:1M -bdkN0:BIPO -bdkF0:vmlinux.img
16    *
17    *  Notes:
18    *
19    *  1) DFORMAT must be run AT LEAST ONCE, in order to create the
20    *     binary partition area. Note also that the filename must be
21    *     provided to write the binary partition.
22    *
23    *  2) All kernel image files must be 32K page aligned!
24    *     To workaround DiskOnChip (TM) binary partition loader page
25    *     write issue. In order for DOC to compute ECC/EDC, you need
26    *     to always write a page (32K) of data (minimum). If the
27    *     image is not page aligned, we simply write N bytes of zeros
28    *     at the end so that the DOC ASIC controller will correctly
29    *     compute the ECC syndrome bytes and all will be good.
30    *     See mkflashimage for more details.
31    *
32    *  3) Note that the CFE loader will never read these bytes,
33    *     we just put them there to keep the DOC asic controller happy.
34    *
35    *   Author:  Mitch Lichtenberg (mpl@broadcom.com)
36    *   Author:  James Dougherty (jfd@broadcom.com)
37    *
38    *********************************************************************
39    *
40    *  Copyright 2000,2001
41    *  Broadcom Corporation. All rights reserved.
42    *
43    *  This software is furnished under license and may be used and
44    *  copied only in accordance with the following terms and
45    *  conditions.  Subject to these conditions, you may download,
46    *  copy, install, use, modify and distribute modified or unmodified
47    *  copies of this software in source and/or binary form.  No title
48    *  or ownership is transferred hereby.
49    *
50    *  1) Any source code used, modified or distributed must reproduce
51    *     and retain this copyright notice and list of conditions as
52    *     they appear in the source file.
53    *
54    *  2) No right is granted to use any trade name, trademark, or
55    *     logo of Broadcom Corporation. Neither the "Broadcom
56    *     Corporation" name nor any trademark or logo of Broadcom
57    *     Corporation may be used to endorse or promote products
58    *     derived from this software without the prior written
59    *     permission of Broadcom Corporation.
60    *
61    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
62    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
63    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
64    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
65    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
66    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
67    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
69    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
70    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
71    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
72    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
73    *     THE POSSIBILITY OF SUCH DAMAGE.
74    ********************************************************************* */
75
76#include "cfe.h"
77
78#include "dev_msys.h"
79#include "dev_flash.h"
80#include "dev_newflash.h"
81
82/*  *********************************************************************
83    *  Forward declarations
84    ********************************************************************* */
85static FLStatus bdkdrv_print_status(const FLStatus bStat);
86
87
88static void bdkdrv_probe(cfe_driver_t *drv,
89			 unsigned long probe_a, unsigned long probe_b,
90			 void *probe_ptr);
91
92static int bdkdrv_open(cfe_devctx_t *ctx);
93static int bdkdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
94static int bdkdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
95static int bdkdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
96static int bdkdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
97static int bdkdrv_close(cfe_devctx_t *ctx);
98
99/*  *********************************************************************
100    *  Device dispatch
101    ********************************************************************* */
102
103const static cfe_devdisp_t bdkdrv_dispatch = {
104    bdkdrv_open,
105    bdkdrv_read,
106    bdkdrv_inpstat,
107    bdkdrv_write,
108    bdkdrv_ioctl,
109    bdkdrv_close,
110    NULL,
111    NULL
112};
113
114const cfe_driver_t bdkdrv = {
115    "M-Systems Binary Partition",
116    "doc",
117    CFE_DEV_OTHER,
118    &bdkdrv_dispatch,
119    bdkdrv_probe
120};
121
122typedef struct bdkdrv_s {
123    newflash_probe_t bdkdrv_probe;	/* data from probe */
124    flash_info_t bdkdrv_info;   /* data from flash info */
125    int bdkdrv_devsize;		/* size reported by driver */
126    int bdkdrv_initialized;	/* true if we've probed already */
127    int bdkdrv_unlocked;
128    FLStatus          status;
129    unsigned long     base, size;
130    unsigned char     sign[SIGNATURE_LEN] ;
131    unsigned long     real_part_size ;
132    unsigned long     image_size ;
133    unsigned long     unit_size ;
134    unsigned long     start_unit;
135    unsigned long     num_blocks;
136    unsigned char     chksum;
137} bdkdrv_t;
138
139
140/*
141 * Output message for FLStatus from M-Systems BDK software.
142 */
143FLStatus
144bdkdrv_print_status(const FLStatus bStat)
145{
146	printf("Error: FLStatus - ") ;
147
148	switch(bStat){
149
150	case flOK:
151		printf("OK\n") ;
152		break ;
153	case flBadFunction:
154		printf("BadFunction\n") ;
155		break ;
156	case flFileNotFound:
157		printf("FileNotFound\n") ;
158		break ;
159	case flPathNotFound:
160		printf("PathNotFound\n") ;
161		break ;
162	case flTooManyOpenFiles:
163		printf("TooManyOpenFiles\n") ;
164		break ;
165	case flNoWriteAccess:
166		printf("NoWriteAccess\n") ;
167		break ;
168	case flBadFileHandle:
169		printf("BadFileHandle\n") ;
170		break ;
171	case flDriveNotAvailable:
172		printf("DriveNotAvailable\n") ;
173		break ;
174	case flNonFATformat:
175		printf("NonFATformat\n") ;
176		break ;
177	case flFormatNotSupported:
178		printf("FormatNotSupported\n") ;
179		break ;
180	case flNoMoreFiles:
181		printf("NoMoreFiles\n") ;
182		break ;
183	case flWriteProtect:
184		printf("WriteProtect\n") ;
185		break ;
186	case flBadDriveHandle:
187		printf("BadDriveHandle\n") ;
188		break ;
189	case flDriveNotReady:
190		printf("DriveNotReady\n") ;
191		break ;
192	case flUnknownCmd:
193		printf("UnknownCmd\n") ;
194		break ;
195	case flBadFormat:
196		printf("BadFormat\n") ;
197		break ;
198	case flBadLength:
199		printf("BadLength\n") ;
200		break ;
201	case flDataError:
202		printf("DataError\n") ;
203		break ;
204	case flUnknownMedia:
205		printf("UnknownMedia\n") ;
206		break ;
207	case flSectorNotFound:
208		printf("SectorNotFound\n") ;
209		break ;
210	case flOutOfPaper:
211		printf("OutOfPaper\n") ;
212		break ;
213	case flWriteFault:
214		printf("WriteFault\n") ;
215		break ;
216	case flReadFault:
217		printf("ReadFault\n") ;
218		break ;
219	case flGeneralFailure:
220		printf("GeneralFailure\n") ;
221		break ;
222	case flDiskChange:
223		printf("DiskChange\n") ;
224		break ;
225	case flVppFailure:
226		printf("VppFailure\n") ;
227		break ;
228	case flBadParameter:
229		printf("BadParameter\n") ;
230		break ;
231	case flNoSpaceInVolume:
232		printf("NoSpaceInVolume\n") ;
233		break ;
234	case flInvalidFATchain:
235		printf("InvalidFATchain\n") ;
236		break ;
237	case flRootDirectoryFull:
238		printf("RootDirectoryFull\n") ;
239		break ;
240	case flNotMounted:
241		printf("NotMounted\n") ;
242		break ;
243	case flPathIsRootDirectory:
244		printf("PathIsRootDirectory\n") ;
245		break ;
246	case flNotADirectory:
247		printf("NotADirectory\n") ;
248		break ;
249	case flDirectoryNotEmpty:
250		printf("DirectoryNotEmpty\n") ;
251		break ;
252	case flFileIsADirectory:
253		printf("FileIsADirectory\n") ;
254		break ;
255	case flAdapterNotFound:
256		printf("AdapterNotFound\n") ;
257		break ;
258	case flFormattingError:
259		printf("FormattingError\n") ;
260		break ;
261	case flNotEnoughMemory:
262		printf("NotEnoughMemory\n") ;
263		break ;
264	case flVolumeTooSmall:
265		printf("VolumeTooSmall\n") ;
266		break ;
267	case flBufferingError:
268		printf("BufferingError\n") ;
269		break ;
270	case flFileAlreadyExists:
271		printf("FileAlreadyExists\n") ;
272		break ;
273	case flIncomplete:
274		printf("Incomplete\n") ;
275		break ;
276	case flTimedOut:
277		printf("TimedOut\n") ;
278		break ;
279	case flTooManyComponents:
280		printf("TooManyComponents\n") ;
281		break ;
282	case flTooManyDrives:
283		printf("TooManyDrives\n") ;
284		break ;
285	case flTooManyBinaryPartitions:
286		printf("TooManyBinaryPartitions\n") ;
287		break ;
288	case flPartitionNotFound:
289		printf("PartitionNotFound\n") ;
290		break ;
291	case flFeatureNotSupported:
292		printf("FeatureNotSupported\n") ;
293		break ;
294	case flWrongVersion:
295		printf("WrongVersion\n") ;
296		break ;
297	case flTooManyBadBlocks:
298		printf("TooManyBadBlocks\n") ;
299		break ;
300	case flNotProtected:
301		printf("NotProtected\n") ;
302		break ;
303	case flUnchangeableProtection:
304		printf("UnchangableProection\n") ;
305		break ;
306	case flBadBBT:
307		printf("BadBBT\n") ;
308		break ;
309	case flInterleaveError:
310		printf("InterlreavError\n") ;
311		break ;
312	case flWrongKey:
313		printf("WrongKey\n") ;
314		break ;
315	case flHWProtection:
316		printf("HWProtection\n") ;
317		break ;
318	case flBadDownload:
319		printf("BadDownload\n") ;
320		break ;
321	default:
322		printf("Unknown status\n") ;
323		break ;
324	}
325
326	return (flOK) ;
327}
328
329
330/*  *********************************************************************
331    *  bdkdrv_probe(drv,probe_a,probe_b,probe_ptr)
332    *
333    *  Device probe routine.  Attach the flash device to
334    *  CFE's device table.
335    *
336    *  Input parameters:
337    *  	   drv - driver descriptor
338    *  	   probe_a - physical address of flash
339    *  	   probe_b - size of flash (bytes)
340    *  	   probe_ptr - unused
341    *
342    *  Return value:
343    *  	   nothing
344    ********************************************************************* */
345
346static void bdkdrv_probe(cfe_driver_t *drv,
347			 unsigned long probe_a, unsigned long probe_b,
348			 void *probe_ptr)
349{
350    bdkdrv_t *softc;
351    char descr[80];
352    newflash_probe_t *probe = (newflash_probe_t *) probe_ptr;
353
354    /*
355     * probe_a is the flash base address
356     * probe_b is the size of the flash
357     * probe_ptr is unused.
358     */
359
360    softc = (bdkdrv_t *) KMALLOC(sizeof(bdkdrv_t),0);
361    if (softc) {
362	memset(softc,0,sizeof(bdkdrv_t));
363
364	softc->base = probe_a;
365	softc->size = probe_b;
366
367	softc->bdkdrv_initialized = 0;
368
369	/* Init BDK API */
370	bdkInit();
371
372	/* Find devices, setup driver metadata state */
373	softc->status = bdkFindDiskOnChip( &softc->base, &softc->size );
374
375	if( softc->status != flOK ) {
376	    printf("ERROR: DiskOnChip not found!\n");
377	    bdkdrv_print_status( softc->status ) ;
378	    bdkExit();
379	}
380
381	/* Get signature of device and check offset of binary partition */
382	tffscpy((void *)softc->sign,
383		(void *)DEFAULTSIGNATURE,BDK_SIGNATURE_NAME);
384	softc->sign[BDK_SIGNATURE_NAME] = '\0';
385
386	softc->bdkdrv_info.flash_type = FLASH_TYPE_FLASH;
387	softc->bdkdrv_info.flash_base = softc->base;
388	softc->bdkdrv_info.flash_size = softc->size;
389	softc->bdkdrv_info.flash_type = FLASH_TYPE_FLASH;
390	softc->bdkdrv_info.flash_flags = 0;
391
392	xsprintf(descr,"%s at %08X size %dMB",
393		 drv->drv_description,
394		 softc->base,
395		 softc->size/(1024*1024));
396
397
398	if (probe) {
399	    /*
400	     * Passed probe structure, do fancy stuff
401	     */
402	    memcpy(&(softc->bdkdrv_probe),probe,sizeof(newflash_probe_t));
403	    if (softc->bdkdrv_probe.flash_nchips == 0) {
404		softc->bdkdrv_probe.flash_nchips = 1;
405	    }
406	}
407
408
409	cfe_attach(drv,softc,NULL,descr);
410    }
411
412}
413
414
415/*  *********************************************************************
416    *  bdkdrv_open(ctx)
417    *
418    *  Called when the flash device is opened.
419    *
420    *  Input parameters:
421    *  	   ctx - device context
422    *
423    *  Return value:
424    *  	   0 if ok else error code
425    ********************************************************************* */
426
427static int bdkdrv_open(cfe_devctx_t *ctx)
428{
429    bdkdrv_t *softc = ctx->dev_softc;
430
431    /*
432     * do initialization
433     */
434
435    if (!softc->bdkdrv_initialized) {
436	/* Get Boot information */
437	softc->start_unit = 0;
438	softc->status = bdkGetBootPartitionInfo( softc->start_unit,
439						 &softc->real_part_size,
440						 &softc->image_size,
441						 &softc->unit_size,
442						 softc->sign );
443	if( softc->status != flOK ) {
444	    printf("Partition with Sign: %s not found\n", softc->sign);
445	    bdkdrv_print_status( softc->status ) ;
446	    bdkExit();
447	    return -1;
448	}
449	printf("Partition: [%s], Size=%ld,"
450	       "UnitSize=%ld\n\t%ld Units,ImageSize=%d (%x)\n",
451	       softc->sign, softc->real_part_size,
452	       softc->unit_size, softc->real_part_size / softc->unit_size,
453	       (int)softc->image_size, (int)softc->image_size);
454
455	softc->num_blocks = softc->real_part_size / softc->unit_size;
456
457	softc->bdkdrv_info.flash_size = softc->image_size;
458	softc->bdkdrv_info.flash_type = FLASH_TYPE_FLASH;
459
460#if 0
461	softc->bdkdrv_probe.flash_nsectors =
462	    softc->image_size / softc->unit_size;
463#else
464	softc->bdkdrv_probe.flash_nsectors = softc->image_size;
465#endif
466	softc->bdkdrv_probe.flash_size = softc->image_size;
467	printf("nblocks=%d, nsectors=%d size=%d\n",
468	       softc->num_blocks, softc->bdkdrv_probe.flash_nsectors,
469	       softc->bdkdrv_probe.flash_size);
470
471	/* Chip Now Ready for I/O */
472	softc->bdkdrv_initialized = TRUE;
473    }
474
475    return 0;
476}
477
478
479/*  *********************************************************************
480    *  bdkdrv_read(ctx,buffer)
481    *
482    *  Read data from the flash device.    The flash device is
483    *  considered to be like a disk (you need to specify the offset).
484    *
485    *  Input parameters:
486    *  	   ctx - device context
487    *  	   buffer - buffer descriptor
488    *
489    *  Return value:
490    *  	   0 if ok, else error code
491    ********************************************************************* */
492
493static int bdkdrv_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
494{
495    bdkdrv_t *softc = ctx->dev_softc;
496    unsigned char *bptr;
497#if 0
498    unsigned char *tmp;
499#endif
500    int offset;
501    int blen, ret, startUnit = 0;
502
503    bptr = buffer->buf_ptr;
504    blen = buffer->buf_length;
505    offset = (int) buffer->buf_offset;
506
507    if (!(softc->bdkdrv_unlocked)) {
508	if ((offset + blen) > softc->real_part_size) {
509	    blen = softc->real_part_size - offset;
510	}
511    }
512    printf("bdkdrv_read: bptr=0x%x blen=%d offset=%d\n",
513	   (unsigned)bptr, blen, offset);
514#if 0
515    tmp = (unsigned char*)KMALLOC(softc->unit_size,0);
516
517    startUnit = offset / softc->unit_size; /* e.g. 512/32K */
518
519    ret = bdkCopyBootAreaInit( startUnit,
520			       softc->image_size, softc->sign );
521
522    /* Read data from binary partition */
523    ret = bdkCopyBootAreaBlock((void*)tmp,
524			       blen,
525			       &softc->chksum);
526
527    memcpy(bptr, tmp + offset, blen);
528    KFREE(tmp);
529#else
530    /* Read data from binary partition */
531    ret = bdkCopyBootArea((void*)bptr,
532			  startUnit,
533			  softc->image_size,
534			  &softc->chksum,
535			  softc->sign);
536#endif
537    if ( ret == flOK ) {
538	printf("DOC read %d bytes OK with checksum 0x%x\n",
539	       (int)blen, (int)softc->chksum);
540    } else {
541	bdkdrv_print_status( ret );
542	return -1;
543    }
544
545    buffer->buf_retlen = blen;
546
547    return 0;
548}
549
550/*  *********************************************************************
551    *  bdkdrv_inpstat(ctx,inpstat)
552    *
553    *  Return "input status".  For flash devices, we always return true.
554    *
555    *  Input parameters:
556    *  	   ctx - device context
557    *  	   inpstat - input status structure
558    *
559    *  Return value:
560    *  	   0 if ok, else error code
561    ********************************************************************* */
562
563static int bdkdrv_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
564{
565    /* bdkdrv_t *softc = ctx->dev_softc; */
566
567    inpstat->inp_status = 1;
568    return 0;
569}
570
571
572
573
574/*  *********************************************************************
575    *  bdkdrv_write(ctx,buffer)
576    *
577    *  Write data to the flash device.    The flash device is
578    *  considered to be like a disk (you need to specify the offset).
579    *
580    *  Input parameters:
581    *  	   ctx - device context
582    *  	   buffer - buffer descriptor
583    *
584    *  Return value:
585    *  	   0 if ok, else error code
586    ********************************************************************* */
587
588static int bdkdrv_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
589{
590#if 0
591    bdkdrv_t *softc = ctx->dev_softc;
592    unsigned char *bptr;
593    int offset;
594    int blen;
595    int res;
596
597    bptr = buffer->buf_ptr;
598    blen = buffer->buf_length;
599    offset = (int) buffer->buf_offset;
600
601    if (!(softc->bdkdrv_unlocked)) {
602	if ((offset + blen) > softc->bdkdrv_devsize) {
603	    blen = softc->bdkdrv_devsize - offset;
604	    }
605	}
606
607    res = FLASHOP_WRITE_BLOCK(softc,offset,bptr,blen);
608
609    buffer->buf_retlen = res;
610
611    /* XXX flush the cache here? */
612
613    return (res == blen) ? 0 : CFE_ERR_IOERR;
614#else
615    printf("bdkdrv_write:\n");
616    return 0;
617#endif
618}
619
620/*  *********************************************************************
621    *  bdkdrv_ioctl(ctx,buffer)
622    *
623    *  Handle special IOCTL functions for the flash.  Flash devices
624    *  support NVRAM information, sector and chip erase, and a
625    *  special IOCTL for updating the running copy of CFE.
626    *
627    *  Input parameters:
628    *  	   ctx - device context
629    *  	   buffer - descriptor for IOCTL parameters
630    *
631    *  Return value:
632    *  	   0 if ok else error
633    ********************************************************************* */
634static int bdkdrv_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
635{
636    bdkdrv_t *softc = ctx->dev_softc;
637    /*
638     * If using flash to store environment, only the last sector
639     * is used for environment stuff.
640     */
641    printf("bdkdrv_ioctl: command=%d\n",
642	   (int)buffer->buf_ioctlcmd);
643    switch ((int)buffer->buf_ioctlcmd) {
644
645	case IOCTL_NVRAM_ERASE:
646	    return CFE_ERR_UNSUPPORTED;
647
648	case IOCTL_NVRAM_GETINFO:
649	    return CFE_ERR_UNSUPPORTED;
650
651	case IOCTL_FLASH_ERASE_SECTOR:
652	    return 0;
653
654	case IOCTL_FLASH_ERASE_ALL:
655	    return CFE_ERR_UNSUPPORTED;
656
657	case IOCTL_FLASH_WRITE_ALL:
658	    return CFE_ERR_UNSUPPORTED;
659
660	case IOCTL_FLASH_GETINFO:
661	    printf("bdkdrv_ioctl: getflashinfo:size=%d\n",
662		   softc->bdkdrv_info.flash_size);
663	    memcpy(buffer->buf_ptr,&(softc->bdkdrv_info),sizeof(flash_info_t));
664	    return 0;
665
666	case IOCTL_FLASH_GETSECTORS:
667	    printf("bdkdrv_ioctl: nsectors=%d\n",
668		   softc->bdkdrv_probe.flash_nsectors);
669
670	    return softc->bdkdrv_probe.flash_nsectors;
671
672	case IOCTL_FLASH_ERASE_RANGE:
673	    return 0;
674
675	case IOCTL_NVRAM_UNLOCK:
676	    softc->bdkdrv_unlocked = TRUE;
677	    break;
678
679	default:
680	    return CFE_ERR_UNSUPPORTED;
681	}
682
683    return CFE_ERR_UNSUPPORTED;
684}
685
686
687/*  *********************************************************************
688    *  bdkdrv_close(ctx)
689    *
690    *  Close the flash device.
691    *
692    *  Input parameters:
693    *  	   ctx - device context
694    *
695    *  Return value:
696    *  	   0
697    ********************************************************************* */
698static int bdkdrv_close(cfe_devctx_t *ctx)
699{
700    /* bdkdrv_t *softc = ctx->dev_softc; */
701
702    /* XXX Invalidate the cache */
703    return 0;
704}
705
706
707