Home | History | Annotate | Line # | Download | only in ebus
flash_ebus.c revision 1.20.8.1
      1  1.20.8.1    martin /*	$NetBSD: flash_ebus.c,v 1.20.8.1 2019/12/08 14:43:16 martin Exp $	*/
      2       1.1     pooka 
      3       1.1     pooka /*-
      4       1.1     pooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5       1.1     pooka  * All rights reserved.
      6       1.1     pooka  *
      7       1.1     pooka  * This code was written by Alessandro Forin and Neil Pittman
      8       1.1     pooka  * at Microsoft Research and contributed to The NetBSD Foundation
      9       1.1     pooka  * by Microsoft Corporation.
     10       1.1     pooka  *
     11       1.1     pooka  * Redistribution and use in source and binary forms, with or without
     12       1.1     pooka  * modification, are permitted provided that the following conditions
     13       1.1     pooka  * are met:
     14       1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     15       1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     16       1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     17       1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     18       1.1     pooka  *    documentation and/or other materials provided with the distribution.
     19       1.1     pooka  *
     20       1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21       1.1     pooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22       1.1     pooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23       1.1     pooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24       1.1     pooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25       1.1     pooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26       1.1     pooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27       1.1     pooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28       1.1     pooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29       1.1     pooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30       1.1     pooka  * POSSIBILITY OF SUCH DAMAGE.
     31       1.1     pooka  */
     32       1.1     pooka 
     33       1.1     pooka #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     34  1.20.8.1    martin __KERNEL_RCSID(0, "$NetBSD: flash_ebus.c,v 1.20.8.1 2019/12/08 14:43:16 martin Exp $");
     35       1.1     pooka 
     36       1.1     pooka /* Driver for the Intel 28F320/640/128 (J3A150) StrataFlash memory device
     37       1.1     pooka  * Extended to include the Intel JS28F256P30T95.
     38       1.1     pooka  */
     39       1.1     pooka 
     40       1.1     pooka #include <sys/param.h>
     41       1.1     pooka #include <sys/systm.h>
     42       1.1     pooka #include <sys/kernel.h>
     43       1.1     pooka #include <sys/proc.h>
     44       1.1     pooka #include <sys/errno.h>
     45       1.1     pooka #include <sys/ioctl.h>
     46       1.1     pooka #include <sys/device.h>
     47       1.1     pooka #include <sys/conf.h>
     48       1.1     pooka #include <sys/file.h>
     49       1.1     pooka #include <sys/stat.h>
     50       1.1     pooka #include <sys/ioctl.h>
     51       1.1     pooka #include <sys/buf.h>
     52       1.1     pooka #include <sys/bufq.h>
     53       1.1     pooka #include <sys/uio.h>
     54       1.1     pooka #include <sys/malloc.h>
     55       1.1     pooka #include <uvm/uvm_extern.h>
     56       1.1     pooka #include <sys/disklabel.h>
     57       1.1     pooka #include <sys/disk.h>
     58       1.1     pooka #include <sys/syslog.h>
     59       1.1     pooka #include <sys/vnode.h>
     60       1.1     pooka #include <sys/kthread.h>
     61       1.1     pooka #include <sys/lock.h>
     62       1.1     pooka #include <sys/queue.h>
     63       1.1     pooka 
     64      1.16  riastrad #include <sys/rndsource.h>
     65       1.1     pooka 
     66       1.1     pooka #include "locators.h"
     67       1.1     pooka #include <prop/proplib.h>
     68       1.1     pooka 
     69       1.1     pooka #include <emips/ebus/ebusvar.h>
     70       1.1     pooka #include <emips/emips/machdep.h>
     71       1.1     pooka #include <machine/emipsreg.h>
     72       1.1     pooka 
     73       1.1     pooka /* Internal config switches
     74       1.1     pooka  */
     75       1.1     pooka #define USE_BUFFERED_WRITES 0    /* Faster, but might not work in some (older) cases */
     76       1.1     pooka #define Verbose 0
     77       1.1     pooka 
     78       1.1     pooka /* Debug tools
     79       1.1     pooka  */
     80       1.1     pooka #define DEBUG_INTR   0x01
     81       1.1     pooka #define DEBUG_XFERS  0x02
     82       1.1     pooka #define DEBUG_STATUS 0x04
     83       1.1     pooka #define DEBUG_FUNCS  0x08
     84       1.1     pooka #define DEBUG_PROBE  0x10
     85       1.1     pooka #define DEBUG_WRITES 0x20
     86       1.1     pooka #define DEBUG_READS  0x40
     87       1.1     pooka #define DEBUG_ERRORS 0x80
     88       1.1     pooka #ifdef DEBUG
     89       1.1     pooka int eflash_debug = DEBUG_ERRORS;
     90       1.1     pooka #define EFLASH_DEBUG(x) (eflash_debug & (x))
     91       1.1     pooka #define DBGME(_lev_,_x_) if ((_lev_) & eflash_debug) _x_
     92       1.1     pooka #else
     93       1.1     pooka #define EFLASH_DEBUG(x) (0)
     94       1.1     pooka #define DBGME(_lev_,_x_)
     95       1.1     pooka #endif
     96       1.1     pooka #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_)
     97       1.1     pooka 
     98       1.1     pooka /* Product ID codes
     99       1.1     pooka  */
    100       1.1     pooka #define MANUF_INTEL  0x89
    101       1.1     pooka #define DEVICE_320   0x16
    102       1.1     pooka #define DEVICE_640   0x17
    103       1.1     pooka #define DEVICE_128   0x18
    104       1.1     pooka #define DEVICE_256   0x19
    105       1.1     pooka 
    106       1.1     pooka /* Table of chips we understand.
    107       1.1     pooka  */
    108       1.1     pooka #define nDELTAS 3
    109       1.1     pooka struct flash_type {
    110       1.1     pooka     struct {
    111       1.1     pooka         uint32_t nSectors;
    112       1.1     pooka         uint32_t nKB;
    113       1.1     pooka     } ft_deltas[nDELTAS];
    114       1.1     pooka     uint8_t ft_manuf_code;
    115       1.1     pooka     uint8_t ft_device_code;
    116       1.1     pooka     uint16_t ft_total_sectors;
    117       1.1     pooka     const char *ft_name;
    118       1.1     pooka };
    119       1.1     pooka 
    120       1.1     pooka static const struct flash_type sector_maps[] = {
    121       1.1     pooka     {
    122       1.1     pooka      {{32,128},{0,0},},
    123       1.1     pooka      MANUF_INTEL, DEVICE_320, 32,   /* a J3 part */
    124       1.1     pooka      "StrataFlash 28F320"
    125       1.1     pooka     },
    126       1.1     pooka     {
    127       1.1     pooka      {{64,128},{0,0},},
    128       1.1     pooka      MANUF_INTEL, DEVICE_640, 64,   /* a J3 part */
    129       1.1     pooka      "StrataFlash 28F640"
    130       1.1     pooka     },
    131       1.1     pooka     {
    132       1.1     pooka      {{128,128},{0,0},},
    133       1.1     pooka      MANUF_INTEL, DEVICE_128, 128,   /* a J3 part */
    134       1.1     pooka      "StrataFlash 28F128"
    135       1.1     pooka     },
    136       1.1     pooka     {
    137       1.1     pooka      {{255,128},{4,32},{0,0}},
    138       1.1     pooka      MANUF_INTEL, DEVICE_256, 259,  /* a P30 part */
    139       1.1     pooka 	 "StrataFlash 28F256"
    140       1.1     pooka     }
    141       1.1     pooka };
    142       1.1     pooka #define nMAPS ((sizeof sector_maps) / (sizeof sector_maps[0]))
    143       1.1     pooka 
    144       1.1     pooka /* Instead of dragging in atavar.h.. */
    145       1.1     pooka struct eflash_bio {
    146       1.1     pooka 	volatile int flags;/* cmd flags */
    147       1.1     pooka #define	ATA_POLL	0x0002	/* poll for completion */
    148       1.1     pooka #define	ATA_SINGLE	0x0008	/* transfer must be done in singlesector mode */
    149       1.1     pooka #define	ATA_READ	0x0020	/* transfer is a read (otherwise a write) */
    150       1.1     pooka #define	ATA_CORR	0x0040	/* transfer had a corrected error */
    151       1.1     pooka 	daddr_t		blkno;	/* block addr */
    152       1.1     pooka 	daddr_t		blkdone;/* number of blks transferred */
    153       1.1     pooka 	size_t		nblks;	/* number of blocks currently transferring */
    154       1.1     pooka 	size_t	    nbytes;	/* number of bytes currently transferring */
    155       1.1     pooka 	char		*databuf;/* data buffer address */
    156       1.1     pooka 	volatile int	error;
    157       1.1     pooka 	u_int32_t	r_error;/* copy of status register */
    158       1.1     pooka #ifdef HAS_BAD144_HANDLING
    159       1.1     pooka 	daddr_t		badsect[127];/* 126 plus trailing -1 marker */
    160       1.1     pooka #endif
    161       1.1     pooka };
    162       1.1     pooka /* End of atavar.h*/
    163       1.1     pooka 
    164       1.1     pooka /* chip-specific functions
    165       1.1     pooka  */
    166       1.1     pooka struct flash_ops;
    167       1.1     pooka 
    168       1.1     pooka /*
    169       1.1     pooka  * Device softc
    170       1.1     pooka  */
    171       1.1     pooka struct eflash_softc {
    172       1.1     pooka 	device_t sc_dev;
    173       1.1     pooka 
    174       1.1     pooka 	/* General disk infos */
    175       1.1     pooka 	struct disk sc_dk;
    176       1.1     pooka 	struct bufq_state *sc_q;
    177       1.1     pooka 	struct callout sc_restart_ch;
    178       1.1     pooka 
    179       1.1     pooka 	/* IDE disk soft states */
    180       1.1     pooka 	struct buf *sc_bp; /* buf being transfered */
    181       1.1     pooka 	struct buf *active_xfer; /* buf handoff to thread  */
    182       1.1     pooka 	struct eflash_bio sc_bio; /* current transfer */
    183       1.1     pooka 
    184       1.1     pooka     struct proc *ch_thread;
    185       1.1     pooka     int ch_flags;
    186       1.1     pooka #define ATACH_SHUTDOWN 0x02        /* thread is shutting down */
    187       1.1     pooka #define ATACH_IRQ_WAIT 0x10        /* thread is waiting for irq */
    188       1.1     pooka #define ATACH_DISABLED 0x80        /* channel is disabled */
    189       1.1     pooka #define ATACH_TH_RUN   0x100       /* the kernel thread is working */
    190       1.1     pooka #define ATACH_TH_RESET 0x200       /* someone ask the thread to reset */
    191       1.1     pooka 
    192       1.1     pooka 	int openings;
    193       1.1     pooka 	int sc_flags;
    194       1.1     pooka #define	EFLASHF_WLABEL	0x004 /* label is writable */
    195       1.1     pooka #define	EFLASHF_LABELLING	0x008 /* writing label */
    196       1.1     pooka #define EFLASHF_LOADED	0x010 /* parameters loaded */
    197       1.1     pooka #define EFLASHF_WAIT	0x020 /* waiting for resources */
    198       1.1     pooka #define EFLASHF_KLABEL	0x080 /* retain label after 'full' close */
    199       1.1     pooka 
    200       1.1     pooka 	int retries; /* number of xfer retry */
    201       1.1     pooka 
    202       1.3       tls 	krndsource_t	rnd_source;
    203       1.1     pooka 
    204       1.1     pooka     /* flash-specific state */
    205       1.1     pooka 	struct _Flash *sc_dp;
    206       1.1     pooka     uint32_t sc_size;
    207       1.1     pooka     uint32_t sc_capacity;
    208       1.1     pooka     paddr_t  sc_base;
    209       1.1     pooka     volatile uint8_t *sc_page0;
    210       1.1     pooka 
    211       1.1     pooka     /* current read-write sector mapping */
    212       1.1     pooka     /*volatile*/ uint8_t *sc_sector;
    213       1.1     pooka     uint32_t sc_sector_size;
    214       1.1     pooka     uint32_t sc_sector_offset;
    215       1.1     pooka #define NOSECTOR ((uint32_t)(~0))
    216       1.1     pooka     int sc_erased;
    217       1.1     pooka 
    218       1.1     pooka     /* device-specificity */
    219       1.1     pooka     uint32_t sc_buffersize;
    220       1.1     pooka     vsize_t sc_max_secsize;
    221       1.1     pooka     unsigned int sc_chips;
    222       1.1     pooka     const struct flash_ops *sc_ops;
    223       1.1     pooka     struct flash_type sc_type;
    224       1.1     pooka };
    225       1.1     pooka 
    226       1.5       chs static int	eflash_ebus_match (device_t, cfdata_t, void *);
    227       1.5       chs static void	eflash_ebus_attach (device_t, device_t, void *);
    228       1.1     pooka 
    229       1.1     pooka CFATTACH_DECL_NEW(flash_ebus, sizeof (struct eflash_softc),
    230       1.1     pooka     eflash_ebus_match, eflash_ebus_attach, NULL, NULL);
    231       1.1     pooka 
    232       1.1     pooka /* implementation decls */
    233       1.1     pooka static int flash_identify(struct eflash_softc*);
    234       1.1     pooka static int KBinSector(struct flash_type * SecMap, unsigned int SecNo);
    235       1.1     pooka static uint32_t SectorStart(struct flash_type * SecMap, int SecNo);
    236       1.1     pooka static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset);
    237       1.1     pooka static void eflash_thread(void *arg);
    238       1.1     pooka static int eflash_read_at (struct eflash_softc *sc, daddr_t start_sector, char *buffer,
    239       1.1     pooka                            size_t nblocks, size_t * pSizeRead);
    240       1.1     pooka static int eflash_write_at(struct eflash_softc *sc, daddr_t start_sector, char *buffer,
    241       1.1     pooka                            size_t nblocks, size_t * pSizeWritten);
    242       1.1     pooka 
    243       1.1     pooka /* Config functions
    244       1.1     pooka  */
    245       1.1     pooka static int
    246       1.5       chs eflash_ebus_match(device_t parent, cfdata_t match, void *aux)
    247       1.1     pooka {
    248       1.1     pooka 	struct ebus_attach_args *ia = aux;
    249       1.1     pooka 	struct _Flash *f = (struct _Flash *)ia->ia_vaddr;
    250       1.1     pooka 
    251       1.1     pooka 	if (strcmp("flash", ia->ia_name) != 0)
    252       1.1     pooka 		return (0);
    253       1.1     pooka 	if ((f == NULL) ||
    254       1.1     pooka 	    ((f->BaseAddressAndTag & FLASHBT_TAG) != PMTTAG_FLASH))
    255       1.1     pooka 		return (0);
    256       1.1     pooka 
    257       1.1     pooka 	return (1);
    258       1.1     pooka }
    259       1.1     pooka 
    260       1.1     pooka static void
    261       1.5       chs eflash_ebus_attach(device_t parent, device_t self, void *aux)
    262       1.1     pooka {
    263       1.1     pooka 	struct ebus_attach_args *ia =aux;
    264       1.1     pooka 	struct eflash_softc *sc = device_private(self);
    265       1.1     pooka     uint32_t base, ctrl;
    266       1.1     pooka     int error;
    267       1.1     pooka 
    268       1.1     pooka     /* Plan.
    269       1.1     pooka      * - mips_map_physmem() (with uncached) first page
    270       1.1     pooka      * - keep it around since we need status ops
    271       1.1     pooka      * - find what type it is.
    272       1.1     pooka      * - then mips_map_physmem() each sector as needed.
    273       1.1     pooka      */
    274       1.1     pooka 
    275       1.1     pooka 	sc->sc_dev = self;
    276       1.1     pooka 	sc->sc_dp = (struct _Flash*)ia->ia_vaddr;
    277       1.1     pooka     base = sc->sc_dp->BaseAddressAndTag & FLASHBT_BASE;
    278       1.1     pooka     ctrl = sc->sc_dp->Control;
    279       1.1     pooka 
    280       1.1     pooka     sc->sc_size = ctrl & FLASHST_SIZE;
    281       1.1     pooka     sc->sc_capacity = sc->sc_size / DEV_BSIZE;
    282       1.1     pooka     sc->sc_base = base;
    283       1.1     pooka     /* The chip is 16bit, so if we get 32bit there are two */
    284       1.1     pooka     sc->sc_chips = (ctrl & FLASHST_BUS_32) ? 2 : 1;
    285       1.1     pooka 
    286       1.1     pooka     /* Map the first page to see what chip we got */
    287       1.1     pooka     sc->sc_page0 = (volatile uint8_t *) mips_map_physmem(base, PAGE_SIZE);
    288       1.1     pooka 
    289       1.1     pooka     if (flash_identify(sc)) {
    290       1.1     pooka         printf(" base %x: %dMB flash memory (%d x %s)\n", base, sc->sc_size >> 20,
    291       1.1     pooka                sc->sc_chips, sc->sc_type.ft_name);
    292       1.1     pooka     } else {
    293       1.1     pooka         /* BUGBUG If we dont identify it stop the driver! */
    294       1.1     pooka         printf(": unknown manufacturer id %x, device id %x\n",
    295       1.1     pooka                sc->sc_type.ft_manuf_code, sc->sc_type.ft_device_code);
    296       1.1     pooka     }
    297       1.1     pooka 
    298       1.7       riz     config_pending_incr(self);
    299       1.1     pooka 
    300       1.1     pooka 	error = kthread_create(PRI_NONE, 0, NULL,
    301       1.1     pooka 	    eflash_thread, sc, NULL, "%s", device_xname(sc->sc_dev));
    302       1.1     pooka 	if (error)
    303       1.1     pooka 		aprint_error_dev(sc->sc_dev,
    304       1.1     pooka 		    "unable to create kernel thread: error %d\n", error);
    305       1.1     pooka }
    306       1.1     pooka 
    307       1.1     pooka /* Implementation functions
    308       1.1     pooka  */
    309       1.1     pooka /* Returns the size in KBytes of a given sector,
    310       1.1     pooka  * or -1 for bad arguments.
    311       1.1     pooka  */
    312       1.1     pooka static int KBinSector(struct flash_type * SecMap, unsigned int SecNo)
    313       1.1     pooka {
    314       1.1     pooka     int i;
    315       1.1     pooka 
    316       1.1     pooka     for (i = 0; i < nDELTAS; i++) {
    317       1.1     pooka         if (SecNo < SecMap->ft_deltas[i].nSectors)
    318       1.1     pooka             return SecMap->ft_deltas[i].nKB;
    319       1.1     pooka         SecNo -= SecMap->ft_deltas[i].nSectors;
    320       1.1     pooka     }
    321       1.1     pooka 
    322       1.1     pooka     return -1;
    323       1.1     pooka }
    324       1.1     pooka 
    325       1.1     pooka #define SectorSize(_map_,_sector_) (1024 * KBinSector(_map_,_sector_))
    326       1.1     pooka 
    327       1.1     pooka /* Whats the starting offset of sector N
    328       1.1     pooka  */
    329       1.1     pooka static uint32_t SectorStart(struct flash_type * SecMap, int SecNo)
    330       1.1     pooka {
    331       1.1     pooka     int i;
    332       1.1     pooka     uint32_t Offset = 0;
    333       1.1     pooka 
    334       1.1     pooka     for (i = 0; i < nDELTAS; i++) {
    335       1.1     pooka         if ((unsigned int)SecNo < SecMap->ft_deltas[i].nSectors)
    336       1.1     pooka             return 1024 * (Offset + (SecMap->ft_deltas[i].nKB * SecNo));
    337       1.1     pooka         SecNo -= SecMap->ft_deltas[i].nSectors;
    338       1.1     pooka         Offset += SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB;
    339       1.1     pooka     }
    340       1.1     pooka 
    341       1.1     pooka     return ~0;
    342       1.1     pooka }
    343       1.1     pooka 
    344       1.1     pooka /* What sector number corresponds to a given offset
    345       1.1     pooka  */
    346       1.1     pooka static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset)
    347       1.1     pooka {
    348       1.1     pooka     unsigned int i;
    349       1.1     pooka     unsigned int SecNo = 0;
    350       1.1     pooka 
    351       1.1     pooka     Offset /= 1024;
    352       1.1     pooka     for (i = 0; i < nDELTAS; i++) {
    353       1.1     pooka         if (Offset < (unsigned int)
    354       1.1     pooka             ((SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB)))
    355       1.1     pooka             return SecNo + (Offset / SecMap->ft_deltas[i].nKB);
    356       1.1     pooka         SecNo += SecMap->ft_deltas[i].nSectors;
    357       1.1     pooka         Offset -= SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB;
    358       1.1     pooka     }
    359       1.1     pooka 
    360       1.1     pooka     return ~0;
    361       1.1     pooka }
    362       1.1     pooka 
    363       1.1     pooka /*
    364       1.1     pooka  * Semi-generic operations
    365       1.1     pooka  */
    366       1.1     pooka struct flash_ops {
    367       1.1     pooka     void (*write_uint8)    (struct eflash_softc *sc, volatile void *Offset, uint8_t Value);
    368       1.1     pooka     void (*read_uint8)     (struct eflash_softc *sc, volatile void *Offset, uint8_t *Value);
    369       1.1     pooka     void (*write_uint16)   (struct eflash_softc *sc, volatile void *Offset, uint16_t Value);
    370       1.1     pooka     void (*read_uint16)    (struct eflash_softc *sc, volatile void *Offset, uint16_t *Value);
    371       1.1     pooka     void (*write_uint32)   (struct eflash_softc *sc, volatile void *Offset, uint32_t Value);
    372       1.1     pooka     void (*read_uint32)    (struct eflash_softc *sc, volatile void *Offset, uint32_t *Value);
    373       1.1     pooka     int  (*program_word)   (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues,
    374       1.1     pooka                             int  Verify, int *nWritten);
    375       1.1     pooka     int  (*program_buffer) (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues,
    376       1.1     pooka                             int  Verify, int *nWritten);
    377       1.1     pooka };
    378       1.1     pooka 
    379       1.1     pooka /*
    380       1.1     pooka  * Hardware access proper, single-chip
    381       1.1     pooka  */
    382       1.1     pooka static void single_write_uint8  (struct eflash_softc *sc,volatile void *Offset,uint8_t Value)
    383       1.1     pooka {
    384       1.1     pooka     volatile uint8_t * Where = Offset;
    385       1.1     pooka     *Where = Value;
    386       1.1     pooka }
    387       1.1     pooka 
    388       1.1     pooka static void single_read_uint8   (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value)
    389       1.1     pooka {
    390       1.1     pooka     volatile uint8_t * Where = Offset;
    391       1.1     pooka     *Value = *Where;
    392       1.1     pooka }
    393       1.1     pooka 
    394       1.1     pooka static void single_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value)
    395       1.1     pooka {
    396       1.1     pooka     volatile uint16_t * Where = Offset;
    397       1.1     pooka     *Where = Value;
    398       1.1     pooka }
    399       1.1     pooka 
    400       1.1     pooka static void single_read_uint16  (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value)
    401       1.1     pooka {
    402       1.1     pooka     volatile uint16_t * Where = Offset;
    403       1.1     pooka     *Value = *Where;
    404       1.1     pooka }
    405       1.1     pooka 
    406       1.1     pooka /* This one should not be used, probably */
    407       1.1     pooka static void single_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value)
    408       1.1     pooka {
    409       1.1     pooka #if 0
    410       1.1     pooka     /* The chip cannot take back-to-back writes */
    411       1.1     pooka     volatile uint32_t * Where = Offset;
    412       1.1     pooka     *Where = Value;
    413       1.1     pooka #else
    414       1.1     pooka     volatile uint8_t * Where = Offset;
    415       1.1     pooka     uint16_t v0, v1;
    416       1.1     pooka 
    417       1.1     pooka     /* Unfortunately, this is bytesex dependent */
    418       1.1     pooka #if (BYTE_ORDER == BIG_ENDIAN)
    419       1.1     pooka     v1 = (uint16_t) Value;
    420       1.1     pooka     v0 = (uint16_t) (Value >> 16);
    421       1.1     pooka #else
    422       1.1     pooka     v0 = (uint16_t) Value;
    423       1.1     pooka     v1 = (uint16_t) (Value >> 16);
    424       1.1     pooka #endif
    425       1.1     pooka     single_write_uint16(sc,Where,v0);
    426       1.1     pooka     single_write_uint16(sc,Where+2,v1);
    427       1.1     pooka #endif
    428       1.1     pooka }
    429       1.1     pooka 
    430       1.1     pooka static void single_read_uint32  (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value)
    431       1.1     pooka {
    432       1.1     pooka     /* back-to-back reads must be ok */
    433       1.1     pooka     volatile uint32_t * Where = Offset;
    434       1.1     pooka     *Value = *Where;
    435       1.1     pooka }
    436       1.1     pooka 
    437       1.1     pooka /*
    438       1.1     pooka  * Hardware access proper, paired-chips
    439       1.1     pooka  * NB: This set of ops assumes two chips in parallel on a 32bit bus,
    440       1.1     pooka  *     each operation is repeated in parallel to both chips
    441       1.1     pooka  */
    442       1.1     pooka static void twin_write_uint8  (struct eflash_softc *sc,volatile void *Offset,uint8_t Value)
    443       1.1     pooka {
    444       1.1     pooka     volatile uint32_t * Where = Offset;
    445       1.1     pooka     uint32_t v = Value | ((uint32_t)Value << 16);
    446       1.1     pooka 
    447       1.1     pooka     v = le32toh(v);
    448       1.1     pooka     *Where = v;
    449       1.1     pooka }
    450       1.1     pooka 
    451       1.1     pooka static void twin_read_uint8   (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value)
    452       1.1     pooka {
    453       1.1     pooka     volatile uint32_t * Where = Offset;
    454       1.1     pooka     uint32_t v;
    455       1.1     pooka     v = *Where;
    456       1.1     pooka     v = le32toh(v);
    457       1.1     pooka     *Value = (uint8_t) v;
    458       1.1     pooka }
    459       1.1     pooka 
    460       1.1     pooka /* This one should *not* be used, error-prone */
    461       1.1     pooka static void twin_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value)
    462       1.1     pooka {
    463       1.1     pooka     volatile uint16_t * Where = Offset;
    464       1.1     pooka     *Where = Value;
    465       1.1     pooka }
    466       1.1     pooka 
    467       1.1     pooka static void twin_read_uint16  (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value)
    468       1.1     pooka {
    469       1.1     pooka     volatile uint16_t * Where = Offset;
    470       1.1     pooka     *Value = *Where;
    471       1.1     pooka }
    472       1.1     pooka 
    473       1.1     pooka static void twin_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value)
    474       1.1     pooka {
    475       1.1     pooka     volatile uint32_t * Where = Offset;
    476       1.1     pooka     Value = le32toh(Value);
    477       1.1     pooka     *Where = Value;
    478       1.1     pooka }
    479       1.1     pooka 
    480       1.1     pooka static void twin_read_uint32  (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value)
    481       1.1     pooka {
    482       1.1     pooka     volatile uint32_t * Where = Offset;
    483       1.1     pooka     uint32_t v;
    484       1.1     pooka     v = *Where;
    485       1.1     pooka     v = le32toh(v);
    486       1.1     pooka     *Value = v;
    487       1.1     pooka }
    488       1.1     pooka 
    489       1.1     pooka /*
    490       1.1     pooka  * Command and status definitions
    491       1.1     pooka  */
    492       1.1     pooka 
    493       1.1     pooka /* Defines for the STATUS register
    494       1.1     pooka  */
    495       1.1     pooka #define ST_reserved          0x01
    496       1.1     pooka #define ST_BLOCK_LOCKED      0x02
    497       1.1     pooka #define ST_PROGRAM_SUSPENDED 0x04
    498       1.1     pooka #define ST_LOW_VOLTAGE       0x08
    499       1.1     pooka #define ST_LOCK_BIT_ERROR    0x10
    500       1.1     pooka #define ST_ERASE_ERROR       0x20
    501       1.1     pooka #define ST_ERASE_SUSPENDED   0x40
    502       1.1     pooka #define ST_READY             0x80
    503       1.1     pooka #define ST_ERASE_MASK        0xee  /* bits to check after erase command */
    504       1.1     pooka #define ST_MASK              0xfe  /* ignore reserved */
    505       1.1     pooka 
    506       1.1     pooka /* Command set (what we use of it)
    507       1.1     pooka  */
    508       1.1     pooka #define CMD_CONFIRM       0xd0
    509       1.1     pooka #define CMD_READ_ARRAY    0xff
    510       1.1     pooka #define CMD_READ_ID       0x90
    511       1.1     pooka #define CMD_READ_STATUS   0x70
    512       1.1     pooka #define CMD_CLEAR_STATUS  0x50
    513       1.1     pooka #define CMD_WRITE_WORD    0x40
    514       1.1     pooka #define CMD_WRITE_BUFFER  0xe8
    515       1.1     pooka #define CMD_ERASE_SETUP   0x20
    516       1.1     pooka #define CMD_ERASE_CONFIRM CMD_CONFIRM
    517       1.1     pooka #define CMD_SET_PREFIX    0x60  /* set read config, lock bits */
    518       1.1     pooka #define CMD_LOCK          0x01
    519       1.1     pooka #define CMD_UNLOCK        CMD_CONFIRM
    520       1.1     pooka /* What we dont use of it
    521       1.1     pooka  */
    522       1.1     pooka #define CMD_READ_QUERY    0x98
    523       1.1     pooka # define BUFFER_BYTES          32
    524       1.1     pooka #define CMD_ERASE_SUSPEND 0xb0
    525       1.1     pooka #define CMD_ERASE_RESUME  CMD_CONFIRM
    526       1.1     pooka #define CMD_CONFIGURATION 0xb8
    527       1.1     pooka #define CMD_PROTECT       0xc0
    528       1.1     pooka 
    529       1.1     pooka /* Enter the Product ID mode (Read Identifier Codes)
    530       1.1     pooka  */
    531       1.1     pooka static void ProductIdEnter(struct eflash_softc *sc)
    532       1.1     pooka {
    533       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ID);
    534       1.1     pooka }
    535       1.1     pooka 
    536       1.1     pooka /* Exit the Product ID mode (enter Read Array mode)
    537       1.1     pooka  */
    538       1.1     pooka static void ProductIdExit(struct eflash_softc *sc)
    539       1.1     pooka {
    540       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY);
    541       1.1     pooka }
    542       1.1     pooka 
    543       1.1     pooka /* Read the status register
    544       1.1     pooka  */
    545       1.1     pooka static uint8_t ReadStatusRegister(struct eflash_softc *sc)
    546       1.1     pooka {
    547       1.1     pooka     uint8_t Status;
    548       1.1     pooka 
    549       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_STATUS);
    550       1.1     pooka     sc->sc_ops->read_uint8(sc,sc->sc_page0,&Status);
    551       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY);
    552       1.1     pooka     return Status;
    553       1.1     pooka }
    554       1.1     pooka 
    555       1.1     pooka /* Clear error bits in status
    556       1.1     pooka  */
    557       1.1     pooka static void ClearStatusRegister(struct eflash_softc *sc)
    558       1.1     pooka {
    559       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_CLEAR_STATUS);
    560       1.1     pooka }
    561       1.1     pooka 
    562       1.1     pooka #if DEBUG
    563       1.1     pooka /* Decode status bits
    564       1.1     pooka  */
    565       1.1     pooka typedef const char *string;
    566       1.1     pooka 
    567       1.1     pooka static void PrintStatus(uint8_t Status)
    568       1.1     pooka {
    569       1.1     pooka     /* BUGBUG there's a %b format I think? */
    570       1.1     pooka     string BitNames[8] = {
    571       1.1     pooka         "reserved", "BLOCK_LOCKED",
    572       1.1     pooka         "PROGRAM_SUSPENDED", "LOW_VOLTAGE",
    573       1.1     pooka         "LOCK_BIT_ERROR", "ERASE_ERROR",
    574       1.1     pooka         "ERASE_SUSPENDED", "READY"
    575       1.1     pooka     };
    576       1.1     pooka     int i;
    577       1.1     pooka     int  OneSet = FALSE;
    578       1.1     pooka 
    579       1.1     pooka     printf("[status %x =",Status);
    580       1.1     pooka     for (i = 0; i < 8; i++) {
    581       1.1     pooka         if (Status & (1<<i)) {
    582       1.1     pooka             printf("%c%s",
    583       1.1     pooka                      (OneSet) ? '|' : ' ',
    584       1.1     pooka                      BitNames[i]);
    585       1.1     pooka             OneSet = TRUE;
    586       1.1     pooka         }
    587       1.1     pooka     }
    588       1.1     pooka     printf("]\n");
    589       1.1     pooka }
    590       1.1     pooka #else
    591       1.1     pooka #define PrintStatus(x)
    592       1.1     pooka #endif
    593       1.1     pooka 
    594       1.1     pooka /*
    595       1.1     pooka  * The device can lock up under certain conditions.
    596       1.1     pooka  * There is no software workaround [must toggle RP# to GND]
    597       1.1     pooka  * Check if it seems that we are in that state.
    598       1.1     pooka  */
    599       1.1     pooka static int  IsIrresponsive(struct eflash_softc *sc)
    600       1.1     pooka {
    601       1.1     pooka     uint8_t Status = ReadStatusRegister(sc);
    602       1.1     pooka 
    603       1.1     pooka     if (Status & ST_READY)
    604       1.1     pooka         return FALSE;
    605       1.1     pooka 
    606      1.18  christos     if ((Status & ST_MASK) ==
    607       1.1     pooka         (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) {
    608       1.1     pooka         /* yes, looks that way */
    609       1.1     pooka         return TRUE;
    610       1.1     pooka     }
    611       1.1     pooka 
    612       1.1     pooka     /* Something is indeed amiss, but we dont really know for sure */
    613       1.1     pooka     PrintStatus(ReadStatusRegister(sc));
    614       1.1     pooka     ClearStatusRegister(sc);
    615       1.1     pooka     PrintStatus(ReadStatusRegister(sc));
    616       1.1     pooka 
    617       1.1     pooka     if ((Status & ST_MASK) ==
    618       1.1     pooka         (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) {
    619       1.1     pooka         /* yes, looks that way */
    620       1.1     pooka         return TRUE;
    621       1.1     pooka     }
    622       1.1     pooka 
    623       1.1     pooka     return FALSE;
    624       1.1     pooka }
    625       1.1     pooka 
    626       1.1     pooka 
    627       1.1     pooka /* Write one 16bit word
    628       1.1     pooka  */
    629       1.1     pooka static int
    630       1.1     pooka single_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
    631       1.1     pooka                   int  Verify, int *nWritten)
    632       1.1     pooka {
    633       1.1     pooka     uint8_t Status;
    634       1.1     pooka     uint16_t i, Data16, Value;
    635       1.1     pooka 
    636       1.1     pooka     *nWritten = 0;
    637       1.1     pooka 
    638       1.1     pooka     Value = Values[0];
    639       1.1     pooka 
    640       1.1     pooka     if (Verify) {
    641       1.1     pooka         sc->sc_ops->read_uint16(sc,Offset,&Data16);
    642       1.1     pooka #ifdef Verbose
    643       1.1     pooka         if (Verbose) {
    644       1.1     pooka             printf("Location %p was x%x\n",
    645       1.1     pooka                    Offset, Data16);
    646       1.1     pooka         }
    647       1.1     pooka #endif
    648       1.1     pooka         if (Data16 != 0xffff)
    649       1.1     pooka             printf("Offset %p not ERASED, wont take.\n",Offset);
    650       1.1     pooka     }
    651       1.1     pooka 
    652       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD);
    653       1.1     pooka     sc->sc_ops->write_uint16(sc,Offset,Value);
    654       1.1     pooka 
    655       1.1     pooka     /* Wait until the operation is completed
    656       1.1     pooka      * Specs say it takes between 210 and 630 us
    657       1.1     pooka      * Errata says 360 TYP and Max=TBD (sic)
    658       1.1     pooka      */
    659       1.1     pooka     DELAY(800);
    660       1.1     pooka 
    661       1.1     pooka     for (i = 0; i < 10; i++) {
    662       1.1     pooka         sc->sc_ops->read_uint8(sc,Offset,&Status);
    663       1.1     pooka         if ((Status & ST_READY)) break;
    664       1.1     pooka         DELAY(100);
    665       1.1     pooka     }
    666       1.1     pooka 
    667       1.1     pooka     ProductIdExit(sc);
    668       1.1     pooka 
    669       1.1     pooka     if (Verify) {
    670       1.1     pooka         sc->sc_ops->read_uint16(sc,Offset,&Data16);
    671       1.1     pooka #ifdef Verbose
    672       1.1     pooka         if (Verbose) {
    673       1.1     pooka             printf("Location %p is now x%x\n",
    674       1.1     pooka                    Offset, Data16);
    675       1.1     pooka         }
    676       1.1     pooka #endif
    677       1.1     pooka         if ((Data16 != Value)) {
    678       1.1     pooka             PrintStatus(Status);
    679       1.1     pooka             printf(". That didnt work, try again.. [%x != %x]\n",
    680       1.1     pooka                    Data16, Value);
    681       1.1     pooka             ClearStatusRegister(sc);
    682       1.1     pooka             return FALSE;
    683       1.1     pooka         }
    684       1.1     pooka     }
    685       1.1     pooka 
    686       1.1     pooka     *nWritten = 2;
    687       1.1     pooka     return TRUE;
    688       1.1     pooka }
    689       1.1     pooka 
    690       1.1     pooka /* Write one buffer, 16bit words at a time
    691       1.1     pooka  */
    692       1.1     pooka static int
    693       1.1     pooka single_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
    694       1.1     pooka                   int  Verify, int *nWritten)
    695       1.1     pooka {
    696       1.1     pooka     uint8_t Status;
    697       1.1     pooka     uint16_t i, Data16, Value = 0;
    698       1.1     pooka     volatile uint8_t *Where = Offset;
    699       1.1     pooka 
    700       1.1     pooka     *nWritten = 0;
    701       1.1     pooka     if (sc->sc_buffersize == 0)
    702       1.1     pooka         return FALSE; /* sanity */
    703       1.1     pooka 
    704       1.1     pooka     if (Verify) {
    705       1.1     pooka         for (i = 0; i < sc->sc_buffersize; i+= 2) {
    706       1.1     pooka             sc->sc_ops->read_uint16(sc,Where+i,&Data16);
    707       1.1     pooka #ifdef Verbose
    708       1.1     pooka             if (Verbose) {
    709       1.1     pooka                 printf("Location %p was x%x\n",
    710       1.1     pooka                        Where+i, Data16);
    711       1.1     pooka             }
    712       1.1     pooka #endif
    713       1.1     pooka 
    714       1.1     pooka             if (Data16 != 0xffff)
    715       1.1     pooka                 printf("Offset %p not ERASED, wont take.\n",Where+i);
    716       1.1     pooka         }
    717       1.1     pooka     }
    718       1.1     pooka 
    719       1.1     pooka     /* Specs say to retry if necessary */
    720       1.1     pooka     for (i = 0; i < 5; i++) {
    721       1.1     pooka         sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER);
    722       1.1     pooka         DELAY(10);
    723       1.1     pooka         sc->sc_ops->read_uint8(sc,Offset,&Status);
    724       1.1     pooka         if ((Status & ST_READY)) break;
    725       1.1     pooka     }
    726       1.1     pooka     if (0 == (Status & ST_READY)) {
    727       1.1     pooka         printf("FAILED program_buffer at Location %p, Status= x%x\n",
    728       1.1     pooka                  Offset, Status);
    729       1.1     pooka         return FALSE;
    730       1.1     pooka     }
    731       1.1     pooka 
    732       1.1     pooka     /* Say how many words we'll be sending */
    733       1.1     pooka     sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/2));
    734       1.1     pooka 
    735       1.1     pooka     /* Send the data */
    736       1.1     pooka     for (i = 0; i < sc->sc_buffersize; i+= 2) {
    737       1.1     pooka         Value = Values[i/2];
    738       1.1     pooka         sc->sc_ops->write_uint16(sc,Where+i,Value);
    739       1.1     pooka         DELAY(10);/*jic*/
    740       1.1     pooka     }
    741       1.1     pooka 
    742       1.1     pooka     /* Write confirmation */
    743       1.1     pooka     sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM);
    744       1.1     pooka 
    745       1.1     pooka     /* Wait until the operation is completed
    746       1.1     pooka      * Specs say it takes between 800 and 2400 us
    747       1.1     pooka      * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above.
    748       1.1     pooka      */
    749       1.1     pooka     DELAY(800);
    750       1.1     pooka 
    751       1.1     pooka     for (i = 0; i < 20; i++) {
    752       1.1     pooka         sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS);
    753       1.1     pooka         sc->sc_ops->read_uint8(sc,Offset,&Status);
    754       1.1     pooka         if ((Status & ST_READY)) break;
    755       1.1     pooka         DELAY(200);
    756       1.1     pooka     }
    757       1.1     pooka 
    758       1.1     pooka     ProductIdExit(sc);
    759       1.1     pooka 
    760       1.1     pooka     /* Verify? */
    761       1.1     pooka     if (Verify) {
    762       1.1     pooka         for (i = 0; i < sc->sc_buffersize; i+= 2) {
    763       1.1     pooka             sc->sc_ops->read_uint16(sc,Where+i,&Data16);
    764       1.1     pooka #ifdef Verbose
    765       1.1     pooka             if (Verbose) {
    766       1.1     pooka                 printf("Location %p is now x%x\n",
    767       1.1     pooka                        Where+i, Data16);
    768       1.1     pooka             }
    769       1.1     pooka #endif
    770       1.1     pooka             Value = Values[i/2];
    771       1.1     pooka 
    772       1.1     pooka             if ((Data16 != Value)) {
    773       1.1     pooka                 PrintStatus(Status);
    774       1.1     pooka                 printf(". That didnt work, try again.. [%x != %x]\n",
    775       1.1     pooka                        Data16, Value);
    776       1.1     pooka                 ClearStatusRegister(sc);
    777       1.1     pooka                 return FALSE;
    778       1.1     pooka             }
    779       1.1     pooka         }
    780       1.1     pooka     }
    781       1.1     pooka 
    782       1.1     pooka     *nWritten = sc->sc_buffersize;
    783       1.1     pooka     return TRUE;
    784       1.1     pooka }
    785       1.1     pooka 
    786       1.1     pooka /* Write one 32bit word
    787       1.1     pooka  */
    788       1.1     pooka static int
    789       1.1     pooka twin_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
    790       1.1     pooka                 int  Verify, int *nWritten)
    791       1.1     pooka {
    792       1.1     pooka     uint8_t Status;
    793       1.1     pooka     uint32_t i, Data32, Value;
    794       1.1     pooka     uint16_t v0, v1;
    795       1.1     pooka 
    796       1.1     pooka     *nWritten = 0;
    797       1.1     pooka 
    798       1.1     pooka     v0 = Values[0];
    799       1.1     pooka     v0 = le16toh(v0);
    800       1.1     pooka     v1 = Values[1];
    801       1.1     pooka     v1 = le16toh(v1);
    802       1.1     pooka     Value = v0 | ((uint32_t)v1 << 16);
    803       1.1     pooka     if (Verify) {
    804       1.1     pooka         sc->sc_ops->read_uint32(sc,Offset,&Data32);
    805       1.1     pooka #ifdef Verbose
    806       1.1     pooka         if (Verbose) {
    807       1.1     pooka             printf("Location %p was x%x\n",
    808       1.1     pooka                    Offset, Data32);
    809       1.1     pooka         }
    810       1.1     pooka #endif
    811       1.1     pooka         if (Data32 != 0xffffffff)
    812       1.1     pooka             printf("Offset %p not ERASED, wont take.\n",Offset);
    813       1.1     pooka     }
    814       1.1     pooka 
    815       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD);
    816       1.1     pooka     sc->sc_ops->write_uint32(sc,Offset,Value);
    817       1.1     pooka 
    818       1.1     pooka     /* Wait until the operation is completed
    819       1.1     pooka      * Specs say it takes between 210 and 630 us
    820       1.1     pooka      * Errata says 360 TYP and Max=TBD (sic)
    821       1.1     pooka      */
    822       1.1     pooka     DELAY(400);
    823       1.1     pooka 
    824       1.1     pooka     for (i = 0; i < 10; i++) {
    825       1.1     pooka         sc->sc_ops->read_uint8(sc,Offset,&Status);
    826       1.1     pooka         if ((Status & ST_READY)) break;
    827       1.1     pooka         DELAY(100);
    828       1.1     pooka     }
    829       1.1     pooka 
    830       1.1     pooka     ProductIdExit(sc);
    831       1.1     pooka 
    832       1.1     pooka     if (Verify) {
    833       1.1     pooka         sc->sc_ops->read_uint32(sc,Offset,&Data32);
    834       1.1     pooka #ifdef Verbose
    835       1.1     pooka         if (Verbose) {
    836       1.1     pooka             printf("Location %p is now x%x\n",
    837       1.1     pooka                    Offset, Data32);
    838       1.1     pooka         }
    839       1.1     pooka #endif
    840       1.1     pooka         if ((Data32 != Value)) {
    841       1.1     pooka             PrintStatus(Status);
    842       1.1     pooka             printf(". That didnt work, try again.. [%x != %x]\n",
    843       1.1     pooka                    Data32, Value);
    844       1.1     pooka             ClearStatusRegister(sc);
    845       1.1     pooka             return FALSE;
    846       1.1     pooka         }
    847       1.1     pooka     }
    848       1.1     pooka 
    849       1.1     pooka     *nWritten = 4;
    850       1.1     pooka     return TRUE;
    851       1.1     pooka }
    852       1.1     pooka 
    853       1.1     pooka /* Write one buffer, 32bit words at a time
    854       1.1     pooka  */
    855       1.1     pooka static int
    856       1.1     pooka twin_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values,
    857       1.1     pooka                 int  Verify, int *nWritten)
    858       1.1     pooka {
    859       1.1     pooka     uint8_t Status;
    860       1.1     pooka     uint32_t i, Data32, Value;
    861       1.1     pooka     uint16_t v0 = 0, v1;
    862       1.1     pooka     volatile uint8_t *Where = Offset;
    863       1.1     pooka 
    864       1.1     pooka     *nWritten = 0;
    865       1.1     pooka     if (sc->sc_buffersize == 0)
    866       1.1     pooka         return FALSE; /* sanity */
    867       1.1     pooka 
    868       1.1     pooka     if (Verify) {
    869       1.1     pooka         for (i = 0; i < sc->sc_buffersize; i+= 4) {
    870       1.1     pooka             sc->sc_ops->read_uint32(sc,Where+i,&Data32);
    871       1.1     pooka #ifdef Verbose
    872       1.1     pooka             if (Verbose) {
    873       1.1     pooka                 printf("Location %p was x%x\n",
    874       1.1     pooka                        Where+i, Data32);
    875       1.1     pooka             }
    876       1.1     pooka #endif
    877       1.1     pooka             if (Data32 != 0xffffffff)
    878       1.1     pooka                 printf("Offset %p not ERASED, wont take.\n",Where+i);
    879       1.1     pooka         }
    880       1.1     pooka     }
    881       1.1     pooka 
    882       1.1     pooka     /* Specs say to retry if necessary */
    883       1.1     pooka     for (i = 0; i < 5; i++) {
    884       1.1     pooka         sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER);
    885       1.1     pooka         DELAY(10);
    886       1.1     pooka         sc->sc_ops->read_uint8(sc,Offset,&Status);
    887       1.1     pooka         if ((Status & ST_READY)) break;
    888       1.1     pooka     }
    889       1.1     pooka     if (0 == (Status & ST_READY)) {
    890       1.1     pooka         printf("FAILED program_buffer at Location %p, Status= x%x\n",
    891       1.1     pooka                  Offset, Status);
    892       1.1     pooka         return FALSE;
    893       1.1     pooka     }
    894       1.1     pooka 
    895       1.1     pooka     /* Say how many words we'll be sending */
    896       1.1     pooka     sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/4)); /* to each twin! */
    897       1.1     pooka 
    898       1.1     pooka     /* Send the data */
    899       1.1     pooka     for (i = 0; i < sc->sc_buffersize; i+= 4) {
    900       1.1     pooka         v0 = Values[i/2];
    901       1.1     pooka         v0 = le16toh(v0);
    902       1.1     pooka         v1 = Values[1+(i/2)];
    903       1.1     pooka         v1 = le16toh(v1);
    904       1.1     pooka         Value = v0 | ((uint32_t)v1 << 16);
    905       1.1     pooka         sc->sc_ops->write_uint32(sc,Where+i,Value);
    906       1.1     pooka         DELAY(10);/*jic*/
    907       1.1     pooka     }
    908       1.1     pooka 
    909       1.1     pooka     /* Write confirmation */
    910       1.1     pooka     sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM);
    911       1.1     pooka 
    912       1.1     pooka     /* Wait until the operation is completed
    913       1.1     pooka      * Specs say it takes between 800 and 2400 us
    914       1.1     pooka      * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above.
    915       1.1     pooka      */
    916       1.1     pooka     DELAY(800);
    917       1.1     pooka 
    918       1.1     pooka     for (i = 0; i < 20; i++) {
    919       1.1     pooka         sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS);
    920       1.1     pooka         sc->sc_ops->read_uint8(sc,Offset,&Status);
    921       1.1     pooka         if ((Status & ST_READY)) break;
    922       1.1     pooka         DELAY(200);
    923       1.1     pooka     }
    924       1.1     pooka 
    925       1.1     pooka     ProductIdExit(sc);
    926       1.1     pooka 
    927       1.1     pooka     /* Verify */
    928       1.1     pooka     if (Verify) {
    929       1.1     pooka         for (i = 0; i < sc->sc_buffersize; i+= 4) {
    930       1.1     pooka             sc->sc_ops->read_uint32(sc,Where+i,&Data32);
    931       1.1     pooka #ifdef Verbose
    932       1.1     pooka             if (Verbose) {
    933       1.1     pooka                 printf("Location %p is now x%x\n",
    934       1.1     pooka                        Where+i, Data32);
    935       1.1     pooka             }
    936       1.1     pooka #endif
    937       1.1     pooka             v0 = Values[i/2];
    938       1.1     pooka             v0 = le16toh(v0);
    939       1.1     pooka             v1 = Values[1+(i/2)];
    940       1.1     pooka             v1 = le16toh(v1);
    941       1.1     pooka             Value = v0 | ((uint32_t)v1 << 16);
    942       1.1     pooka 
    943       1.1     pooka             if ((Data32 != Value)) {
    944       1.1     pooka                 PrintStatus(Status);
    945       1.1     pooka                 printf(". That didnt work, try again.. [%x != %x]\n",
    946       1.1     pooka                        Data32, Value);
    947       1.1     pooka                 ClearStatusRegister(sc);
    948       1.1     pooka                 return FALSE;
    949       1.1     pooka             }
    950       1.1     pooka         }
    951       1.1     pooka     }
    952       1.1     pooka 
    953       1.1     pooka     *nWritten = sc->sc_buffersize;
    954       1.1     pooka     return TRUE;
    955       1.1     pooka }
    956       1.1     pooka 
    957       1.1     pooka /* Is there a lock on a given sector
    958       1.1     pooka  */
    959       1.1     pooka static int IsSectorLocked(struct eflash_softc *sc, uint8_t *secptr)
    960       1.1     pooka {
    961       1.1     pooka     uint8_t Data, Data1;
    962       1.1     pooka 
    963       1.1     pooka     ProductIdEnter(sc);
    964       1.1     pooka     /* Lockout info is at address 2 of the given sector, meaning A0=0 A1=1.
    965       1.1     pooka      */
    966       1.1     pooka     sc->sc_ops->read_uint8(sc,secptr+(0x0002*2*sc->sc_chips),&Data);
    967       1.1     pooka     sc->sc_ops->read_uint8(sc,secptr+(0x0003*2*sc->sc_chips),&Data1);
    968       1.1     pooka 
    969       1.1     pooka     ProductIdExit(sc);
    970       1.1     pooka 
    971       1.1     pooka     return (Data & 1);
    972       1.1     pooka }
    973       1.1     pooka 
    974       1.1     pooka /* Remove the write-lock to a sector
    975       1.1     pooka  */
    976       1.1     pooka static void SectorUnLock(struct eflash_softc *sc, uint8_t *secptr)
    977       1.1     pooka {
    978       1.1     pooka     uint8_t Status;
    979       1.1     pooka     int i;
    980       1.1     pooka 
    981       1.1     pooka     DBGME(DEBUG_FUNCS,printf("%s: Unlocking sector %d [ptr %p] ...\n",
    982       1.1     pooka 	device_xname(sc->sc_dev), sc->sc_sector_offset, secptr));
    983       1.1     pooka 
    984       1.1     pooka     sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_SET_PREFIX);
    985       1.1     pooka     sc->sc_ops->write_uint8(sc,secptr,CMD_UNLOCK);
    986       1.1     pooka 
    987       1.1     pooka     /* Wait until the unlock is complete.
    988       1.1     pooka      * Specs say this takes between 64 and 75 usecs.
    989       1.1     pooka      */
    990       1.1     pooka     DELAY(100);
    991       1.1     pooka 
    992       1.1     pooka     for (i = 0; i < 10; i++) {
    993       1.1     pooka         sc->sc_ops->read_uint8(sc,secptr,&Status);
    994       1.1     pooka         if ((Status & ST_READY)) break;
    995       1.1     pooka         DELAY(100);
    996       1.1     pooka     }
    997       1.1     pooka 
    998       1.1     pooka     ProductIdExit(sc);
    999       1.1     pooka 
   1000       1.1     pooka     if ((Status & ST_MASK) == ST_READY) {
   1001       1.1     pooka         DBGME(DEBUG_FUNCS,printf("%s: Unlocked ok.\n",
   1002       1.1     pooka 	    device_xname(sc->sc_dev)));
   1003       1.1     pooka         return;
   1004       1.1     pooka     }
   1005       1.1     pooka 
   1006       1.1     pooka     PrintStatus(Status);
   1007       1.1     pooka     DBGME(DEBUG_ERRORS,printf("%s: Unlock of sector %d NOT completed (status=%x).\n",
   1008       1.1     pooka                               device_xname(sc->sc_dev),
   1009       1.1     pooka 			      sc->sc_sector_offset, Status));
   1010       1.1     pooka     ClearStatusRegister(sc);
   1011       1.1     pooka }
   1012       1.1     pooka 
   1013       1.1     pooka 
   1014       1.1     pooka /* Erase one sector
   1015       1.1     pooka  */
   1016       1.1     pooka static int  SectorErase(struct eflash_softc *sc, void *secptr)
   1017       1.1     pooka {
   1018       1.1     pooka     uint8_t Status = 0;
   1019       1.1     pooka     uint16_t i;
   1020       1.1     pooka 
   1021       1.1     pooka     DBGME(DEBUG_FUNCS,printf("%s: Erasing sector %d [ptr %p] ...\n",
   1022       1.1     pooka 	device_xname(sc->sc_dev), sc->sc_sector_offset, secptr));
   1023       1.1     pooka 
   1024       1.1     pooka     /* On some chips we just cannot avoid the locking business.
   1025       1.1     pooka      */
   1026       1.1     pooka     if ((sc->sc_chips == 1) &&
   1027       1.1     pooka         IsSectorLocked(sc,secptr))
   1028       1.1     pooka         SectorUnLock(sc,secptr);
   1029       1.1     pooka 
   1030       1.1     pooka     sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_SETUP);
   1031       1.1     pooka     sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_CONFIRM);
   1032       1.1     pooka 
   1033       1.1     pooka     /* Wait until the erase is actually completed
   1034       1.1     pooka      * Specs say it will take between 1 and 5 seconds.
   1035       1.1     pooka      * Errata says it takes 2 sec min and 25 sec max.
   1036       1.1     pooka      * Double that before giving up.
   1037       1.1     pooka      */
   1038       1.1     pooka     for (i = 0; i < 20; i++) {
   1039       1.1     pooka         /* Sleep for at least 2 seconds
   1040       1.1     pooka          */
   1041       1.1     pooka         tsleep(sc,PWAIT,"erase", hz * 2);
   1042       1.1     pooka 
   1043       1.1     pooka         sc->sc_ops->read_uint8(sc,secptr,&Status);
   1044       1.1     pooka         if ((Status & ST_READY)) break;
   1045       1.1     pooka         PrintStatus(Status);
   1046       1.1     pooka     }
   1047       1.1     pooka 
   1048       1.1     pooka     ProductIdExit(sc);
   1049       1.1     pooka 
   1050       1.1     pooka     if ((Status & ST_ERASE_MASK) == ST_READY) {
   1051       1.1     pooka         DBGME(DEBUG_FUNCS,printf("%s: Erased ok.\n", device_xname(sc->sc_dev)));
   1052       1.1     pooka         return 0;
   1053       1.1     pooka     }
   1054       1.1     pooka 
   1055       1.1     pooka     PrintStatus(Status);
   1056       1.1     pooka     DBGME(DEBUG_ERRORS,printf("%s: Erase of sector %d NOT completed (status=%x).\n",
   1057       1.1     pooka                               device_xname(sc->sc_dev),
   1058       1.1     pooka 			      sc->sc_sector_offset, Status));
   1059       1.1     pooka 
   1060       1.1     pooka     ClearStatusRegister(sc);
   1061       1.1     pooka     return EIO;
   1062       1.1     pooka }
   1063       1.1     pooka 
   1064       1.1     pooka 
   1065       1.1     pooka 
   1066       1.1     pooka /* Write (a portion of) a sector
   1067       1.1     pooka  */
   1068       1.1     pooka static size_t eflash_write_sector(struct eflash_softc *sc, char *Buffer, size_t n,
   1069       1.1     pooka                                uint8_t *Offset, int Verify)
   1070       1.1     pooka {
   1071       1.1     pooka     size_t i;
   1072       1.1     pooka 
   1073       1.1     pooka     /* Make sure the device is not screwed up
   1074       1.1     pooka      */
   1075       1.1     pooka     if (IsIrresponsive(sc)) {
   1076       1.1     pooka         printf("FLASH is locked-up (or mapped cacheable?), wont work. ");
   1077       1.1     pooka     }
   1078       1.1     pooka 
   1079       1.1     pooka     for (i = 0; i < n;) {
   1080       1.1     pooka         int nTries;
   1081       1.1     pooka         int nWritten = 0;/*we expect 2 or 4 */
   1082       1.1     pooka 
   1083       1.1     pooka         if (sc->sc_buffersize && ((n-i) >= sc->sc_buffersize)) {
   1084       1.1     pooka             for (nTries = 0; nTries < 5; nTries++)
   1085       1.1     pooka                 if (sc->sc_ops->program_buffer(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten))
   1086       1.1     pooka                     break;
   1087       1.1     pooka         } else {
   1088       1.1     pooka             for (nTries = 0; nTries < 5; nTries++)
   1089       1.1     pooka                 if (sc->sc_ops->program_word(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten))
   1090       1.1     pooka                     break;
   1091       1.1     pooka         }
   1092       1.1     pooka         Offset += nWritten;
   1093       1.1     pooka         i += nWritten;
   1094       1.1     pooka         if (nWritten == 0)
   1095       1.1     pooka             break;
   1096       1.1     pooka     }
   1097       1.1     pooka     return i;
   1098       1.1     pooka }
   1099       1.1     pooka 
   1100       1.1     pooka /* Identify type and the sector map of the FLASH.
   1101       1.1     pooka  * Argument is the base address of the device and the count of chips on the bus (1/2)
   1102       1.1     pooka  * Returns FALSE if failed
   1103       1.1     pooka  */
   1104       1.1     pooka static const struct flash_ops single_ops = {
   1105       1.1     pooka     single_write_uint8,
   1106       1.1     pooka     single_read_uint8,
   1107       1.1     pooka     single_write_uint16,
   1108       1.1     pooka     single_read_uint16,
   1109       1.1     pooka     single_write_uint32,
   1110       1.1     pooka     single_read_uint32,
   1111       1.1     pooka     single_program_word,
   1112       1.1     pooka     single_program_buffer
   1113       1.1     pooka };
   1114       1.1     pooka 
   1115       1.1     pooka static const struct flash_ops twin_ops = {
   1116       1.1     pooka     twin_write_uint8,
   1117       1.1     pooka     twin_read_uint8,
   1118       1.1     pooka     twin_write_uint16,
   1119       1.1     pooka     twin_read_uint16,
   1120       1.1     pooka     twin_write_uint32,
   1121       1.1     pooka     twin_read_uint32,
   1122       1.1     pooka     twin_program_word,
   1123       1.1     pooka     twin_program_buffer
   1124       1.1     pooka };
   1125       1.1     pooka 
   1126       1.1     pooka static int  flash_identify(struct eflash_softc *sc)
   1127       1.1     pooka {
   1128       1.1     pooka     uint8_t Mid, Did;
   1129       1.1     pooka     int i;
   1130       1.1     pooka 
   1131       1.1     pooka     if (sc->sc_chips > 1)
   1132       1.1     pooka         sc->sc_ops = &twin_ops;
   1133       1.1     pooka     else
   1134       1.1     pooka         sc->sc_ops = &single_ops;
   1135       1.1     pooka 
   1136       1.1     pooka     sc->sc_buffersize = 0;
   1137       1.1     pooka #if USE_BUFFERED_WRITES
   1138       1.1     pooka     sc->sc_buffersize = BUFFER_BYTES * sc->sc_chips;
   1139       1.1     pooka #endif
   1140       1.1     pooka     sc->sc_sector = NULL;
   1141       1.1     pooka     sc->sc_sector_size = 0;
   1142       1.1     pooka     sc->sc_sector_offset = NOSECTOR;
   1143       1.1     pooka     sc->sc_erased = FALSE;
   1144       1.1     pooka 
   1145       1.1     pooka     ProductIdEnter(sc);
   1146       1.1     pooka     sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0000*2*sc->sc_chips),&Mid);
   1147       1.1     pooka     sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0001*2*sc->sc_chips),&Did);
   1148       1.1     pooka     ProductIdExit(sc);
   1149       1.1     pooka 
   1150       1.1     pooka     sc->sc_type.ft_manuf_code = Mid;
   1151       1.1     pooka     sc->sc_type.ft_device_code = Did;
   1152       1.1     pooka 
   1153       1.1     pooka     for (i = 0; i < nMAPS; i++) {
   1154       1.1     pooka         if ((sector_maps[i].ft_manuf_code == Mid) && (sector_maps[i].ft_device_code == Did)) {
   1155       1.1     pooka             int j;
   1156       1.1     pooka             uint32_t ms = 0;
   1157       1.1     pooka             sc->sc_type = sector_maps[i];
   1158       1.1     pooka             /* double the sector sizes if twin-chips */
   1159       1.1     pooka             for (j = 0; j < nDELTAS; j++) {
   1160       1.1     pooka                 sc->sc_type.ft_deltas[j].nKB *= sc->sc_chips;
   1161       1.1     pooka                 if (ms < sc->sc_type.ft_deltas[j].nKB)
   1162       1.1     pooka                     ms = sc->sc_type.ft_deltas[j].nKB;
   1163       1.1     pooka             }
   1164       1.1     pooka             sc->sc_max_secsize = ms * 1024;
   1165       1.1     pooka             return TRUE;
   1166       1.1     pooka         }
   1167       1.1     pooka     }
   1168       1.1     pooka 
   1169       1.1     pooka     return FALSE;
   1170       1.1     pooka }
   1171       1.1     pooka 
   1172       1.1     pooka /* Common code for read&write argument validation
   1173       1.1     pooka  */
   1174       1.1     pooka static int eflash_validate(struct eflash_softc *sc, daddr_t start, size_t *pSize, void **pSrc)
   1175       1.1     pooka {
   1176       1.1     pooka     daddr_t Size;
   1177       1.1     pooka     uint32_t sec;
   1178       1.1     pooka     size_t secsize, secstart;
   1179       1.1     pooka 
   1180       1.1     pooka     /* Validate args
   1181       1.1     pooka      */
   1182       1.1     pooka     if (start >= sc->sc_capacity) {
   1183       1.1     pooka         *pSize = 0;
   1184       1.1     pooka         DBGME(DEBUG_ERRORS,printf("eflash::ValidateArg(%qx) EOF\n", start));
   1185       1.1     pooka         return E2BIG;
   1186       1.1     pooka     }
   1187       1.1     pooka 
   1188       1.1     pooka     /* Map sector if not already
   1189       1.1     pooka      */
   1190       1.1     pooka     sec = SectorNumber(&sc->sc_type, start << DEV_BSHIFT);
   1191       1.1     pooka     secsize = SectorSize( &sc->sc_type, sec);
   1192       1.1     pooka     secstart = SectorStart(&sc->sc_type,sec);
   1193       1.1     pooka     if (sec != sc->sc_sector_offset) {
   1194       1.1     pooka         int error;
   1195       1.1     pooka 
   1196       1.1     pooka         /* unmap previous first */
   1197       1.1     pooka         if (sc->sc_sector_offset != NOSECTOR) {
   1198       1.1     pooka             DBGME(DEBUG_FUNCS,printf("%s: unmap %p %zx\n",
   1199       1.1     pooka 		device_xname(sc->sc_dev), sc->sc_sector, sc->sc_sector_size));
   1200       1.1     pooka             iounaccess((vaddr_t)sc->sc_sector, sc->sc_sector_size);
   1201       1.1     pooka             sc->sc_sector_offset = NOSECTOR;
   1202       1.1     pooka         }
   1203       1.1     pooka 
   1204       1.1     pooka         /* map new */
   1205       1.1     pooka         error = ioaccess((vaddr_t)sc->sc_sector,
   1206       1.1     pooka                          secstart + sc->sc_base,
   1207       1.1     pooka                          secsize);
   1208       1.2   tsutsui         DBGME(DEBUG_FUNCS,printf("%s: mapped %p %zx -> %zx %d\n",
   1209       1.1     pooka 	    device_xname(sc->sc_dev),
   1210       1.1     pooka 	    sc->sc_sector, secsize, secstart + sc->sc_base,error));
   1211       1.1     pooka         if (error) return error;
   1212       1.1     pooka 
   1213       1.1     pooka         /* Update state. We have to assume the sector was not erased. Sigh. */
   1214       1.1     pooka         sc->sc_sector_offset = sec;
   1215       1.1     pooka         sc->sc_sector_size = secsize;
   1216       1.1     pooka         sc->sc_erased = FALSE;
   1217       1.1     pooka     }
   1218       1.1     pooka 
   1219       1.1     pooka     /* Adjust size if necessary
   1220       1.1     pooka      */
   1221       1.1     pooka     Size = start + *pSize; /* last sector */
   1222       1.1     pooka     if (Size > sc->sc_capacity) {
   1223       1.1     pooka         /* At most this many sectors
   1224       1.1     pooka          */
   1225       1.1     pooka         Size = sc->sc_capacity - start;
   1226       1.1     pooka         *pSize = (size_t)Size;
   1227       1.1     pooka     }
   1228       1.1     pooka     if (*pSize > (secsize >> DEV_BSHIFT)) {
   1229       1.1     pooka         *pSize = secsize >> DEV_BSHIFT;
   1230       1.1     pooka     }
   1231       1.1     pooka 
   1232       1.1     pooka     *pSrc = sc->sc_sector + (start << DEV_BSHIFT) - secstart;
   1233       1.1     pooka 
   1234       1.1     pooka     DBGME(DEBUG_FUNCS,printf("%s: Validate %qx %zd %p\n",
   1235       1.1     pooka 	device_xname(sc->sc_dev), start,*pSize, *pSrc));
   1236       1.1     pooka     return 0;
   1237       1.1     pooka }
   1238       1.1     pooka 
   1239       1.1     pooka static int eflash_read_at (struct eflash_softc *sc,
   1240       1.1     pooka                            daddr_t start_sector, char *buffer, size_t nblocks,
   1241       1.1     pooka                            size_t * pSizeRead)
   1242       1.1     pooka {
   1243       1.1     pooka     int error;
   1244       1.1     pooka     uint32_t SizeRead = 0;
   1245       1.1     pooka     void *src;
   1246       1.1     pooka 
   1247       1.1     pooka     DBGME(DEBUG_XFERS|DEBUG_READS,printf("%s: EflashReadAt(%qx %p %zd %p)\n",
   1248       1.1     pooka                      device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeRead));
   1249       1.1     pooka 
   1250       1.1     pooka     /* Validate & trim arguments
   1251       1.1     pooka      */
   1252       1.1     pooka     error = eflash_validate(sc, start_sector, &nblocks, &src);
   1253       1.1     pooka 
   1254       1.1     pooka     /* Copy data if
   1255       1.1     pooka      */
   1256       1.1     pooka     if (error == 0) {
   1257       1.1     pooka         SizeRead = nblocks;
   1258       1.1     pooka         memcpy(buffer, src, nblocks << DEV_BSHIFT);
   1259       1.1     pooka     }
   1260       1.1     pooka 
   1261       1.1     pooka     if (pSizeRead)
   1262       1.1     pooka         *pSizeRead = SizeRead;
   1263       1.1     pooka     return error;
   1264       1.1     pooka }
   1265       1.1     pooka 
   1266       1.1     pooka /* Write SIZE bytes to device.
   1267       1.1     pooka  */
   1268       1.1     pooka static int eflash_write_at (struct eflash_softc *sc,
   1269       1.1     pooka                            daddr_t start_sector, char *buffer, size_t nblocks,
   1270       1.1     pooka                            size_t * pSizeWritten)
   1271       1.1     pooka {
   1272       1.1     pooka     int error;
   1273       1.1     pooka     void *src;
   1274       1.1     pooka     size_t SizeWritten = 0;
   1275       1.1     pooka 
   1276       1.1     pooka     DBGME(DEBUG_XFERS|DEBUG_WRITES,printf("%s: EflashWriteAt(%qx %p %zd %p)\n",
   1277       1.1     pooka                      device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeWritten));
   1278       1.1     pooka 
   1279       1.1     pooka     /* Validate & trim arguments
   1280       1.1     pooka      */
   1281       1.1     pooka     error = eflash_validate(sc, start_sector, &nblocks, &src);
   1282       1.1     pooka 
   1283       1.1     pooka     if (error == 0) {
   1284       1.1     pooka         /* Do we have to erase it */
   1285       1.1     pooka         if (! sc->sc_erased) {
   1286       1.1     pooka 
   1287       1.1     pooka             error = SectorErase(sc,src);
   1288       1.1     pooka             if (error)
   1289       1.1     pooka                 goto Out;
   1290       1.1     pooka             sc->sc_erased = TRUE;
   1291       1.1     pooka         }
   1292       1.1     pooka         SizeWritten = eflash_write_sector(sc, buffer, nblocks << DEV_BSHIFT, src, TRUE);
   1293       1.1     pooka         SizeWritten >>= DEV_BSHIFT;
   1294       1.1     pooka     }
   1295       1.1     pooka 
   1296       1.1     pooka  Out:
   1297       1.1     pooka     if (pSizeWritten)
   1298       1.1     pooka         *pSizeWritten = SizeWritten;
   1299       1.1     pooka     return error;
   1300       1.1     pooka }
   1301       1.1     pooka 
   1302       1.1     pooka /* Rest of code lifted with mods from the dev\ata\wd.c driver
   1303       1.1     pooka  */
   1304       1.1     pooka 
   1305       1.1     pooka /*
   1306       1.1     pooka  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
   1307       1.1     pooka  *
   1308       1.1     pooka  * Redistribution and use in source and binary forms, with or without
   1309       1.1     pooka  * modification, are permitted provided that the following conditions
   1310       1.1     pooka  * are met:
   1311       1.1     pooka  * 1. Redistributions of source code must retain the above copyright
   1312       1.1     pooka  *	notice, this list of conditions and the following disclaimer.
   1313       1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
   1314       1.1     pooka  *	notice, this list of conditions and the following disclaimer in the
   1315       1.1     pooka  *	documentation and/or other materials provided with the distribution.
   1316       1.1     pooka  *
   1317       1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   1318       1.1     pooka  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   1319       1.1     pooka  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   1320       1.1     pooka  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   1321       1.1     pooka  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   1322       1.1     pooka  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   1323       1.1     pooka  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   1324       1.1     pooka  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   1325       1.1     pooka  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   1326       1.1     pooka  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1327       1.1     pooka  */
   1328       1.1     pooka 
   1329       1.1     pooka /*-
   1330       1.1     pooka  * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
   1331       1.1     pooka  * All rights reserved.
   1332       1.1     pooka  *
   1333       1.1     pooka  * This code is derived from software contributed to The NetBSD Foundation
   1334       1.1     pooka  * by Charles M. Hannum and by Onno van der Linden.
   1335       1.1     pooka  *
   1336       1.1     pooka  * Redistribution and use in source and binary forms, with or without
   1337       1.1     pooka  * modification, are permitted provided that the following conditions
   1338       1.1     pooka  * are met:
   1339       1.1     pooka  * 1. Redistributions of source code must retain the above copyright
   1340       1.1     pooka  *    notice, this list of conditions and the following disclaimer.
   1341       1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
   1342       1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
   1343       1.1     pooka  *    documentation and/or other materials provided with the distribution.
   1344       1.1     pooka  * 3. All advertising materials mentioning features or use of this software
   1345       1.1     pooka  *    must display the following acknowledgement:
   1346       1.1     pooka  *        This product includes software developed by the NetBSD
   1347       1.1     pooka  *        Foundation, Inc. and its contributors.
   1348       1.1     pooka  * 4. Neither the name of The NetBSD Foundation nor the names of its
   1349       1.1     pooka  *    contributors may be used to endorse or promote products derived
   1350       1.1     pooka  *    from this software without specific prior written permission.
   1351       1.1     pooka  *
   1352       1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   1353       1.1     pooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   1354       1.1     pooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   1355       1.1     pooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   1356       1.1     pooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   1357       1.1     pooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   1358       1.1     pooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   1359       1.1     pooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   1360       1.1     pooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   1361       1.1     pooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   1362       1.1     pooka  * POSSIBILITY OF SUCH DAMAGE.
   1363       1.1     pooka  */
   1364       1.1     pooka 
   1365       1.1     pooka static const char ST506[] = "ST506";
   1366       1.1     pooka 
   1367       1.1     pooka #define	EFLASHIORETRIES_SINGLE 4	/* number of retries before single-sector */
   1368       1.1     pooka #define	EFLASHIORETRIES	5	/* number of retries before giving up */
   1369       1.1     pooka #define	RECOVERYTIME hz/2	/* time to wait before retrying a cmd */
   1370       1.1     pooka 
   1371       1.1     pooka #define	EFLASHUNIT(dev)		DISKUNIT(dev)
   1372       1.1     pooka #define	EFLASHPART(dev)		DISKPART(dev)
   1373       1.1     pooka #define	EFLASHMINOR(unit, part)	DISKMINOR(unit, part)
   1374       1.1     pooka #define	MAKEEFLASHDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
   1375       1.1     pooka 
   1376       1.1     pooka #define	EFLASHLABELDEV(dev)	(MAKEEFLASHDEV(major(dev), EFLASHUNIT(dev), RAW_PART))
   1377       1.1     pooka 
   1378       1.1     pooka void	eflashperror(const struct eflash_softc *);
   1379       1.1     pooka 
   1380       1.1     pooka extern struct cfdriver eflash_cd;
   1381       1.1     pooka 
   1382       1.1     pooka dev_type_open(eflashopen);
   1383       1.1     pooka dev_type_close(eflashclose);
   1384       1.1     pooka dev_type_read(eflashread);
   1385       1.1     pooka dev_type_write(eflashwrite);
   1386       1.1     pooka dev_type_ioctl(eflashioctl);
   1387       1.1     pooka dev_type_strategy(eflashstrategy);
   1388       1.1     pooka dev_type_dump(eflashdump);
   1389       1.1     pooka dev_type_size(eflashsize);
   1390       1.1     pooka 
   1391       1.1     pooka const struct bdevsw eflash_bdevsw = {
   1392       1.8  dholland 	.d_open = eflashopen,
   1393       1.8  dholland 	.d_close = eflashclose,
   1394       1.8  dholland 	.d_strategy = eflashstrategy,
   1395       1.8  dholland 	.d_ioctl = eflashioctl,
   1396       1.8  dholland 	.d_dump = eflashdump,
   1397       1.8  dholland 	.d_psize = eflashsize,
   1398       1.9  dholland 	.d_discard = nodiscard,
   1399       1.8  dholland 	.d_flag = D_DISK
   1400       1.1     pooka };
   1401       1.1     pooka 
   1402       1.1     pooka const struct cdevsw eflash_cdevsw = {
   1403       1.8  dholland 	.d_open = eflashopen,
   1404       1.8  dholland 	.d_close = eflashclose,
   1405       1.8  dholland 	.d_read = eflashread,
   1406       1.8  dholland 	.d_write = eflashwrite,
   1407       1.8  dholland 	.d_ioctl = eflashioctl,
   1408       1.8  dholland 	.d_stop = nostop,
   1409       1.8  dholland 	.d_tty = notty,
   1410       1.8  dholland 	.d_poll = nopoll,
   1411       1.8  dholland 	.d_mmap = nommap,
   1412       1.8  dholland 	.d_kqfilter = nokqfilter,
   1413      1.10  dholland 	.d_discard = nodiscard,
   1414       1.8  dholland 	.d_flag = D_DISK
   1415       1.1     pooka };
   1416       1.1     pooka 
   1417       1.1     pooka void  eflashgetdefaultlabel(struct eflash_softc *, struct disklabel *);
   1418       1.1     pooka void  eflashgetdisklabel(struct eflash_softc *);
   1419       1.1     pooka void  eflashstart(void *);
   1420       1.5       chs void  __eflashstart(struct eflash_softc *, struct buf *);
   1421       1.1     pooka void  eflashrestart(void *);
   1422       1.1     pooka void  eflashattach(struct eflash_softc *);
   1423       1.5       chs int   eflashdetach(device_t, int);
   1424       1.5       chs int   eflashactivate(device_t, enum devact);
   1425       1.1     pooka 
   1426       1.1     pooka void  eflashdone(struct eflash_softc *);
   1427       1.6  christos static void eflash_set_geometry(struct eflash_softc *sc);
   1428       1.1     pooka 
   1429      1.17   mlelstv struct dkdriver eflashdkdriver = {
   1430      1.17   mlelstv 	.d_strategy = eflashstrategy,
   1431      1.17   mlelstv 	.d_minphys = minphys
   1432      1.17   mlelstv };
   1433       1.1     pooka 
   1434       1.1     pooka #ifdef HAS_BAD144_HANDLING
   1435       1.1     pooka static void bad144intern(struct eflash_softc *);
   1436       1.1     pooka #endif
   1437       1.1     pooka 
   1438       1.1     pooka static void eflash_wedges(void *arg);
   1439       1.1     pooka 
   1440       1.1     pooka void
   1441       1.1     pooka eflashattach(struct eflash_softc *sc)
   1442       1.1     pooka {
   1443       1.5       chs 	device_t self = sc->sc_dev;
   1444       1.1     pooka 	char pbuf[9];
   1445       1.1     pooka 	DEBUG_PRINT(("%s: eflashattach\n",  device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE);
   1446       1.1     pooka 
   1447       1.1     pooka 	callout_init(&sc->sc_restart_ch, 0);
   1448       1.1     pooka 	bufq_alloc(&sc->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
   1449       1.1     pooka 
   1450       1.1     pooka     sc->openings = 1; /* wazziz?*/
   1451       1.1     pooka 
   1452       1.1     pooka 	aprint_naive("\n");
   1453       1.1     pooka 
   1454       1.1     pooka     /* setup all required fields so that if the attach fails we are ok */
   1455       1.1     pooka 	sc->sc_dk.dk_driver = &eflashdkdriver;
   1456       1.1     pooka 	sc->sc_dk.dk_name = device_xname(sc->sc_dev);
   1457       1.1     pooka 
   1458       1.1     pooka 	format_bytes(pbuf, sizeof(pbuf), sc->sc_capacity * DEV_BSIZE);
   1459       1.1     pooka 	aprint_normal("%s: %s, %d cyl, %d head, %d sec, %d bytes/sect x %llu sectors\n",
   1460       1.5       chs 	    device_xname(self), pbuf, 1, 1, sc->sc_capacity,
   1461       1.1     pooka 	    DEV_BSIZE, (unsigned long long)sc->sc_capacity);
   1462       1.1     pooka 
   1463       1.6  christos     eflash_set_geometry(sc);
   1464       1.1     pooka 
   1465       1.1     pooka 	/*
   1466       1.1     pooka 	 * Attach the disk structure. We fill in dk_info later.
   1467       1.1     pooka 	 */
   1468       1.1     pooka 	disk_attach(&sc->sc_dk);
   1469       1.1     pooka 
   1470       1.1     pooka 	rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
   1471      1.11       tls 			  RND_TYPE_DISK, RND_FLAG_DEFAULT);
   1472       1.1     pooka 
   1473       1.1     pooka }
   1474       1.1     pooka 
   1475       1.1     pooka int
   1476       1.5       chs eflashactivate(device_t self, enum devact act)
   1477       1.1     pooka {
   1478       1.1     pooka 	int rv = 0;
   1479       1.1     pooka 
   1480       1.1     pooka 	DEBUG_PRINT(("eflashactivate %x\n",  act), DEBUG_FUNCS | DEBUG_PROBE);
   1481       1.1     pooka 
   1482       1.1     pooka 	switch (act) {
   1483       1.1     pooka 	case DVACT_DEACTIVATE:
   1484       1.1     pooka 		/*
   1485       1.1     pooka 		 * Nothing to do; we key off the device's DVF_ACTIVATE.
   1486       1.1     pooka 		 */
   1487       1.1     pooka 		break;
   1488       1.1     pooka 	default:
   1489       1.1     pooka 		rv = EOPNOTSUPP;
   1490       1.1     pooka 		break;
   1491       1.1     pooka 	}
   1492       1.1     pooka 	return (rv);
   1493       1.1     pooka }
   1494       1.1     pooka 
   1495       1.1     pooka int
   1496       1.5       chs eflashdetach(device_t self, int flags)
   1497       1.1     pooka {
   1498       1.1     pooka 	struct eflash_softc *sc = device_private(self);
   1499       1.1     pooka 	int s, bmaj, cmaj, i, mn;
   1500       1.1     pooka 
   1501       1.1     pooka 	DEBUG_PRINT(("%s: eflashdetach\n",  device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE);
   1502       1.1     pooka 
   1503       1.1     pooka 	/* locate the major number */
   1504       1.1     pooka 	bmaj = bdevsw_lookup_major(&eflash_bdevsw);
   1505       1.1     pooka 	cmaj = cdevsw_lookup_major(&eflash_cdevsw);
   1506       1.1     pooka 
   1507       1.1     pooka 	/* Nuke the vnodes for any open instances. */
   1508       1.1     pooka 	for (i = 0; i < MAXPARTITIONS; i++) {
   1509       1.1     pooka 		mn = EFLASHMINOR(device_unit(self), i);
   1510       1.1     pooka 		vdevgone(bmaj, mn, mn, VBLK);
   1511       1.1     pooka 		vdevgone(cmaj, mn, mn, VCHR);
   1512       1.1     pooka 	}
   1513       1.1     pooka 
   1514       1.1     pooka 	/* Delete all of our wedges. */
   1515       1.1     pooka 	dkwedge_delall(&sc->sc_dk);
   1516       1.1     pooka 
   1517       1.1     pooka 	s = splbio();
   1518       1.1     pooka 
   1519       1.1     pooka 	/* Kill off any queued buffers. */
   1520       1.1     pooka 	bufq_drain(sc->sc_q);
   1521       1.1     pooka 
   1522       1.1     pooka 	/*sc->atabus->ata_killpending(sc->drvp);*/
   1523       1.1     pooka 
   1524       1.1     pooka 	splx(s);
   1525      1.19  pgoyette 	bufq_free(sc->sc_q);
   1526       1.1     pooka 
   1527       1.1     pooka 	/* Detach disk. */
   1528       1.1     pooka 	disk_detach(&sc->sc_dk);
   1529       1.1     pooka 
   1530       1.1     pooka 	/* Unhook the entropy source. */
   1531       1.1     pooka 	rnd_detach_source(&sc->rnd_source);
   1532       1.1     pooka 
   1533       1.1     pooka 	/*sc->drvp->drive_flags = 0; -- no drive any more here */
   1534       1.1     pooka 
   1535       1.1     pooka 	return (0);
   1536       1.1     pooka }
   1537       1.1     pooka 
   1538       1.1     pooka extern int	dkwedge_autodiscover;
   1539       1.1     pooka 
   1540       1.1     pooka /* Aux temp thread to avoid deadlock when doing the partitio.. ahem wedges thing.
   1541       1.1     pooka  */
   1542       1.1     pooka static void
   1543       1.1     pooka eflash_wedges(void *arg)
   1544       1.1     pooka {
   1545       1.1     pooka 	struct eflash_softc *sc = (struct eflash_softc*)arg;
   1546       1.1     pooka 
   1547       1.1     pooka     DBGME(DEBUG_STATUS,printf("%s: wedges started for %p\n", sc->sc_dk.dk_name, sc));
   1548       1.1     pooka 
   1549       1.1     pooka 	/* Discover wedges on this disk. */
   1550       1.1     pooka     dkwedge_autodiscover = 1;
   1551       1.1     pooka 	dkwedge_discover(&sc->sc_dk);
   1552       1.1     pooka 
   1553       1.7       riz     config_pending_decr(sc->sc_dev);
   1554       1.1     pooka 
   1555       1.1     pooka     DBGME(DEBUG_STATUS,printf("%s: wedges thread done for %p\n", device_xname(sc->sc_dev), sc));
   1556       1.1     pooka 	kthread_exit(0);
   1557       1.1     pooka }
   1558       1.1     pooka 
   1559       1.1     pooka static void
   1560       1.1     pooka eflash_thread(void *arg)
   1561       1.1     pooka {
   1562       1.1     pooka 	struct eflash_softc *sc = (struct eflash_softc*)arg;
   1563       1.1     pooka 	struct buf *bp;
   1564       1.1     pooka     vaddr_t addr;
   1565       1.1     pooka 	int s, error;
   1566       1.1     pooka 
   1567       1.1     pooka     DBGME(DEBUG_STATUS,printf("%s: thread started for %p\n", device_xname(sc->sc_dev), sc));
   1568       1.1     pooka 
   1569       1.1     pooka     s = splbio();
   1570       1.1     pooka     eflashattach(sc);
   1571       1.1     pooka     splx(s);
   1572       1.1     pooka 
   1573       1.1     pooka     /* Allocate a VM window large enough to map the largest sector
   1574       1.1     pooka      * BUGBUG We could risk it and allocate/free on open/close?
   1575       1.1     pooka      */
   1576       1.1     pooka     addr = uvm_km_alloc(kernel_map, sc->sc_max_secsize, 0, UVM_KMF_VAONLY);
   1577       1.1     pooka     if (addr == 0)
   1578       1.1     pooka         panic("eflash_thread: kernel map full (%lx)", (long unsigned)sc->sc_max_secsize);
   1579       1.1     pooka     sc->sc_sector = (/*volatile*/ uint8_t *) addr;
   1580       1.1     pooka     sc->sc_sector_size = 0;
   1581       1.1     pooka     sc->sc_sector_offset = NOSECTOR;
   1582       1.1     pooka 
   1583       1.1     pooka 	error = kthread_create(PRI_NONE, 0, NULL,
   1584       1.1     pooka 	    eflash_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev));
   1585       1.1     pooka 	if (error) {
   1586       1.1     pooka 		aprint_error_dev(sc->sc_dev, "wedges: unable to create kernel "
   1587       1.1     pooka 		    "thread: error %d\n", error);
   1588       1.1     pooka 		/* XXX: why continue? */
   1589       1.1     pooka 	}
   1590       1.1     pooka 
   1591       1.1     pooka 
   1592       1.1     pooka     DBGME(DEBUG_STATUS,printf("%s: thread service active for %p\n", device_xname(sc->sc_dev), sc));
   1593       1.1     pooka 
   1594       1.1     pooka     s = splbio();
   1595       1.1     pooka 	for (;;) {
   1596       1.1     pooka         /* Get next I/O request, wait if necessary
   1597       1.1     pooka          */
   1598       1.1     pooka 		if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 &&
   1599       1.1     pooka 		    (sc->active_xfer == NULL)) {
   1600       1.1     pooka 			sc->ch_flags &= ~ATACH_TH_RUN;
   1601       1.1     pooka 			(void) tsleep(&sc->ch_thread, PRIBIO, "eflashth", 0);
   1602       1.1     pooka 			sc->ch_flags |= ATACH_TH_RUN;
   1603       1.1     pooka 		}
   1604       1.1     pooka 		if (sc->ch_flags & ATACH_SHUTDOWN) {
   1605       1.1     pooka 			break;
   1606       1.1     pooka         }
   1607       1.1     pooka         bp = sc->active_xfer;
   1608       1.1     pooka         sc->active_xfer = NULL;
   1609       1.1     pooka 		if (bp != NULL) {
   1610       1.1     pooka 
   1611       1.1     pooka             size_t sz = DEV_BSIZE, bnow;
   1612       1.1     pooka 
   1613       1.1     pooka             DBGME(DEBUG_XFERS,printf("%s: task %p %x %p %qx %d (%zd)\n", device_xname(sc->sc_dev), bp,
   1614       1.1     pooka                                      sc->sc_bio.flags, sc->sc_bio.databuf, sc->sc_bio.blkno,
   1615       1.1     pooka                                      sc->sc_bio.nbytes, sc->sc_bio.nblks));
   1616       1.1     pooka 
   1617       1.1     pooka             sc->sc_bio.error = 0;
   1618       1.1     pooka             for (; sc->sc_bio.nblks > 0;) {
   1619       1.1     pooka 
   1620       1.1     pooka                 bnow = sc->sc_bio.nblks;
   1621       1.1     pooka                 if (sc->sc_bio.flags & ATA_SINGLE) bnow = 1;
   1622       1.1     pooka 
   1623       1.1     pooka                 if (sc->sc_bio.flags & ATA_READ) {
   1624       1.1     pooka                     sc->sc_bio.error =
   1625       1.1     pooka                         eflash_read_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
   1626       1.1     pooka                 } else {
   1627       1.1     pooka                     sc->sc_bio.error =
   1628       1.1     pooka                         eflash_write_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz);
   1629       1.1     pooka                 }
   1630       1.1     pooka 
   1631       1.1     pooka                 if (sc->sc_bio.error)
   1632       1.1     pooka                     break;
   1633       1.1     pooka 
   1634       1.1     pooka                 sc->sc_bio.blkno += sz; /* in blocks */
   1635       1.1     pooka                 sc->sc_bio.nblks -= sz;
   1636       1.1     pooka                 sc->sc_bio.blkdone += sz;
   1637       1.1     pooka                 sz = sz << DEV_BSHIFT; /* in bytes */
   1638       1.1     pooka                 sc->sc_bio.databuf += sz;
   1639       1.1     pooka                 sc->sc_bio.nbytes  -= sz;
   1640       1.1     pooka             }
   1641       1.1     pooka 
   1642       1.1     pooka             eflashdone(sc);
   1643       1.1     pooka         }
   1644       1.1     pooka 	}
   1645       1.1     pooka 
   1646       1.1     pooka 	splx(s);
   1647       1.1     pooka 	sc->ch_thread = NULL;
   1648       1.1     pooka 	wakeup(&sc->ch_flags);
   1649       1.1     pooka 
   1650       1.1     pooka     DBGME(DEBUG_STATUS,printf("%s: thread service terminated for %p\n", device_xname(sc->sc_dev), sc));
   1651       1.1     pooka 
   1652       1.1     pooka 	kthread_exit(0);
   1653       1.1     pooka }
   1654       1.1     pooka 
   1655       1.1     pooka 
   1656       1.1     pooka /*
   1657       1.1     pooka  * Read/write routine for a buffer.  Validates the arguments and schedules the
   1658       1.1     pooka  * transfer.  Does not wait for the transfer to complete.
   1659       1.1     pooka  */
   1660       1.1     pooka void
   1661       1.1     pooka eflashstrategy(struct buf *bp)
   1662       1.1     pooka {
   1663       1.1     pooka 	struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(bp->b_dev));
   1664       1.1     pooka 	struct disklabel *lp = sc->sc_dk.dk_label;
   1665       1.1     pooka 	daddr_t blkno;
   1666       1.1     pooka 	int s;
   1667       1.1     pooka 
   1668       1.1     pooka 	DEBUG_PRINT(("%s: eflashstrategy %lld\n", device_xname(sc->sc_dev), bp->b_blkno),
   1669       1.1     pooka 	    DEBUG_XFERS);
   1670       1.1     pooka 
   1671       1.1     pooka 	/* Valid request?  */
   1672       1.1     pooka 	if (bp->b_blkno < 0 ||
   1673       1.1     pooka 	    (bp->b_bcount % lp->d_secsize) != 0 ||
   1674       1.1     pooka 	    (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
   1675       1.1     pooka 		bp->b_error = EINVAL;
   1676       1.1     pooka 		goto done;
   1677       1.1     pooka 	}
   1678       1.1     pooka 
   1679       1.1     pooka 	/* If device invalidated (e.g. media change, door open), error. */
   1680       1.1     pooka 	if ((sc->sc_flags & EFLASHF_LOADED) == 0) {
   1681       1.1     pooka 		bp->b_error = EIO;
   1682       1.1     pooka 		goto done;
   1683       1.1     pooka 	}
   1684       1.1     pooka 
   1685       1.1     pooka 	/* If it's a null transfer, return immediately. */
   1686       1.1     pooka 	if (bp->b_bcount == 0)
   1687       1.1     pooka 		goto done;
   1688       1.1     pooka 
   1689       1.1     pooka 	/*
   1690       1.1     pooka 	 * Do bounds checking, adjust transfer. if error, process.
   1691       1.1     pooka 	 * If end of partition, just return.
   1692       1.1     pooka 	 */
   1693       1.1     pooka 	if (EFLASHPART(bp->b_dev) == RAW_PART) {
   1694       1.1     pooka 		if (bounds_check_with_mediasize(bp, DEV_BSIZE,
   1695       1.1     pooka 		    sc->sc_capacity) <= 0)
   1696       1.1     pooka 			goto done;
   1697       1.1     pooka 	} else {
   1698       1.1     pooka 		if (bounds_check_with_label(&sc->sc_dk, bp,
   1699       1.1     pooka 		    (sc->sc_flags & (EFLASHF_WLABEL|EFLASHF_LABELLING)) != 0) <= 0)
   1700       1.1     pooka 			goto done;
   1701       1.1     pooka 	}
   1702       1.1     pooka 
   1703       1.1     pooka 	/*
   1704       1.1     pooka 	 * Now convert the block number to absolute and put it in
   1705       1.1     pooka 	 * terms of the device's logical block size.
   1706       1.1     pooka 	 */
   1707       1.1     pooka 	if (lp->d_secsize >= DEV_BSIZE)
   1708       1.1     pooka 		blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
   1709       1.1     pooka 	else
   1710       1.1     pooka 		blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
   1711       1.1     pooka 
   1712       1.1     pooka 	if (EFLASHPART(bp->b_dev) != RAW_PART)
   1713       1.1     pooka 		blkno += lp->d_partitions[EFLASHPART(bp->b_dev)].p_offset;
   1714       1.1     pooka 
   1715       1.1     pooka 	bp->b_rawblkno = blkno;
   1716       1.1     pooka 
   1717       1.1     pooka 	/* Queue transfer on drive, activate drive and controller if idle. */
   1718       1.1     pooka 	s = splbio();
   1719       1.1     pooka 	bufq_put(sc->sc_q, bp);
   1720       1.1     pooka 	eflashstart(sc);
   1721       1.1     pooka 	splx(s);
   1722       1.1     pooka 	return;
   1723       1.1     pooka done:
   1724       1.1     pooka 	/* Toss transfer; we're done early. */
   1725       1.1     pooka 	bp->b_resid = bp->b_bcount;
   1726       1.1     pooka 	biodone(bp);
   1727       1.1     pooka }
   1728       1.1     pooka 
   1729       1.1     pooka /*
   1730       1.1     pooka  * Queue a drive for I/O.
   1731       1.1     pooka  */
   1732       1.1     pooka void
   1733       1.1     pooka eflashstart(void *arg)
   1734       1.1     pooka {
   1735       1.1     pooka 	struct eflash_softc *sc = arg;
   1736       1.1     pooka 	struct buf *bp = NULL;
   1737       1.1     pooka 
   1738       1.1     pooka 	DEBUG_PRINT(("%s: eflashstart\n", device_xname(sc->sc_dev)),
   1739       1.1     pooka 	    DEBUG_XFERS);
   1740       1.1     pooka 	while (sc->openings > 0) {
   1741       1.1     pooka 
   1742       1.1     pooka 		/* Is there a buf for us ? */
   1743       1.1     pooka 		if ((bp = bufq_get(sc->sc_q)) == NULL)
   1744       1.1     pooka 			return;
   1745       1.1     pooka 
   1746       1.1     pooka 		/*
   1747       1.1     pooka 		 * Make the command. First lock the device
   1748       1.1     pooka 		 */
   1749       1.1     pooka 		sc->openings--;
   1750       1.1     pooka 
   1751       1.1     pooka 		sc->retries = 0;
   1752       1.1     pooka 		__eflashstart(sc, bp);
   1753       1.1     pooka 	}
   1754       1.1     pooka }
   1755       1.1     pooka 
   1756       1.1     pooka void
   1757       1.1     pooka __eflashstart(struct eflash_softc *sc, struct buf *bp)
   1758       1.1     pooka {
   1759       1.1     pooka 	DEBUG_PRINT(("%s: __eflashstart %p\n", device_xname(sc->sc_dev), bp),
   1760       1.1     pooka 	    DEBUG_XFERS);
   1761       1.1     pooka 
   1762       1.1     pooka 	sc->sc_bp = bp;
   1763       1.1     pooka 	/*
   1764       1.1     pooka 	 * If we're retrying, retry in single-sector mode. This will give us
   1765       1.1     pooka 	 * the sector number of the problem, and will eventually allow the
   1766       1.1     pooka 	 * transfer to succeed.
   1767       1.1     pooka 	 */
   1768       1.1     pooka 	if (sc->retries >= EFLASHIORETRIES_SINGLE)
   1769       1.1     pooka 		sc->sc_bio.flags = ATA_SINGLE;
   1770       1.1     pooka 	else
   1771       1.1     pooka 		sc->sc_bio.flags = 0;
   1772       1.1     pooka 	if (bp->b_flags & B_READ)
   1773       1.1     pooka 		sc->sc_bio.flags |= ATA_READ;
   1774       1.1     pooka 	sc->sc_bio.blkno = bp->b_rawblkno;
   1775       1.1     pooka 	sc->sc_bio.blkdone = 0;
   1776       1.1     pooka 	sc->sc_bio.nbytes = bp->b_bcount;
   1777       1.1     pooka 	sc->sc_bio.nblks  = bp->b_bcount >> DEV_BSHIFT;
   1778       1.1     pooka 	sc->sc_bio.databuf = bp->b_data;
   1779       1.1     pooka 	/* Instrumentation. */
   1780       1.1     pooka 	disk_busy(&sc->sc_dk);
   1781       1.1     pooka     sc->active_xfer = bp;
   1782       1.1     pooka     wakeup(&sc->ch_thread);
   1783       1.1     pooka }
   1784       1.1     pooka 
   1785       1.1     pooka void
   1786       1.1     pooka eflashdone(struct eflash_softc *sc)
   1787       1.1     pooka {
   1788       1.1     pooka 	struct buf *bp = sc->sc_bp;
   1789       1.1     pooka 	const char *errmsg;
   1790       1.1     pooka 	int do_perror = 0;
   1791       1.1     pooka 
   1792       1.1     pooka 	DEBUG_PRINT(("%s: eflashdone %p\n", device_xname(sc->sc_dev), bp),
   1793       1.1     pooka 	    DEBUG_XFERS);
   1794       1.1     pooka 
   1795       1.1     pooka 	if (bp == NULL)
   1796       1.1     pooka 		return;
   1797       1.1     pooka 
   1798       1.1     pooka 	bp->b_resid = sc->sc_bio.nbytes;
   1799       1.1     pooka 	switch (sc->sc_bio.error) {
   1800       1.1     pooka 	case ETIMEDOUT:
   1801       1.1     pooka 		errmsg = "device timeout";
   1802       1.1     pooka         do_perror = 1;
   1803       1.1     pooka 		goto retry;
   1804       1.1     pooka 	case EBUSY:
   1805       1.1     pooka 		errmsg = "device stuck";
   1806       1.1     pooka retry:		/* Just reset and retry. Can we do more ? */
   1807       1.1     pooka 		/*eflash_reset(sc);*/
   1808       1.1     pooka 		diskerr(bp, "flash", errmsg, LOG_PRINTF,
   1809       1.1     pooka 		    sc->sc_bio.blkdone, sc->sc_dk.dk_label);
   1810       1.1     pooka 		if (sc->retries < EFLASHIORETRIES)
   1811       1.1     pooka 			printf(", retrying");
   1812       1.1     pooka 		printf("\n");
   1813       1.1     pooka 		if (do_perror)
   1814       1.1     pooka 			eflashperror(sc);
   1815       1.1     pooka 		if (sc->retries < EFLASHIORETRIES) {
   1816       1.1     pooka 			sc->retries++;
   1817       1.1     pooka 			callout_reset(&sc->sc_restart_ch, RECOVERYTIME,
   1818       1.1     pooka 			    eflashrestart, sc);
   1819       1.1     pooka 			return;
   1820       1.1     pooka 		}
   1821       1.1     pooka 
   1822       1.1     pooka 		bp->b_error = EIO;
   1823       1.1     pooka 		break;
   1824       1.1     pooka 	case 0:
   1825       1.1     pooka         if ((sc->sc_bio.flags & ATA_CORR) || sc->retries > 0)
   1826       1.1     pooka 			printf("%s: soft error (corrected)\n",
   1827       1.1     pooka 			    device_xname(sc->sc_dev));
   1828       1.1     pooka 		break;
   1829       1.1     pooka 	case ENODEV:
   1830       1.1     pooka 	case E2BIG:
   1831       1.1     pooka 		bp->b_error = EIO;
   1832       1.1     pooka 		break;
   1833       1.1     pooka 	}
   1834       1.1     pooka 	disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid),
   1835       1.1     pooka 	    (bp->b_flags & B_READ));
   1836       1.1     pooka 	rnd_add_uint32(&sc->rnd_source, bp->b_blkno);
   1837       1.1     pooka     biodone(bp);
   1838       1.1     pooka     sc->openings++;
   1839       1.1     pooka 	eflashstart(sc);
   1840       1.1     pooka }
   1841       1.1     pooka 
   1842       1.1     pooka void
   1843       1.1     pooka eflashrestart(void *v)
   1844       1.1     pooka {
   1845       1.1     pooka 	struct eflash_softc *sc = v;
   1846       1.1     pooka 	struct buf *bp = sc->sc_bp;
   1847       1.1     pooka 	int s;
   1848       1.1     pooka 	DEBUG_PRINT(("%s: eflashrestart\n", device_xname(sc->sc_dev)),
   1849       1.1     pooka 	    DEBUG_XFERS);
   1850       1.1     pooka 
   1851       1.1     pooka 	s = splbio();
   1852       1.1     pooka 	__eflashstart(v, bp);
   1853       1.1     pooka 	splx(s);
   1854       1.1     pooka }
   1855       1.1     pooka 
   1856       1.1     pooka int
   1857       1.1     pooka eflashread(dev_t dev, struct uio *uio, int flags)
   1858       1.1     pooka {
   1859       1.1     pooka 	DEBUG_PRINT(("eflashread\n"), DEBUG_XFERS);
   1860       1.1     pooka 	return (physio(eflashstrategy, NULL, dev, B_READ, minphys, uio));
   1861       1.1     pooka }
   1862       1.1     pooka 
   1863       1.1     pooka int
   1864       1.1     pooka eflashwrite(dev_t dev, struct uio *uio, int flags)
   1865       1.1     pooka {
   1866       1.1     pooka 	DEBUG_PRINT(("eflashwrite\n"), DEBUG_XFERS);
   1867       1.1     pooka 	return (physio(eflashstrategy, NULL, dev, B_WRITE, minphys, uio));
   1868       1.1     pooka }
   1869       1.1     pooka 
   1870       1.1     pooka int
   1871       1.1     pooka eflashopen(dev_t dev, int flag, int fmt, struct lwp *l)
   1872       1.1     pooka {
   1873       1.1     pooka 	struct eflash_softc *sc;
   1874       1.1     pooka 	int part, error;
   1875       1.1     pooka 
   1876       1.2   tsutsui 	DEBUG_PRINT(("eflashopen %" PRIx64 "\n", dev), DEBUG_FUNCS);
   1877       1.1     pooka 	sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
   1878       1.1     pooka 	if (sc == NULL)
   1879       1.1     pooka 		return (ENXIO);
   1880       1.1     pooka 
   1881       1.1     pooka 	if (! device_is_active(sc->sc_dev))
   1882       1.1     pooka 		return (ENODEV);
   1883       1.1     pooka 
   1884       1.1     pooka 	part = EFLASHPART(dev);
   1885       1.1     pooka 
   1886       1.1     pooka 	mutex_enter(&sc->sc_dk.dk_openlock);
   1887       1.1     pooka 
   1888       1.1     pooka 	/*
   1889       1.1     pooka 	 * If there are wedges, and this is not RAW_PART, then we
   1890       1.1     pooka 	 * need to fail.
   1891       1.1     pooka 	 */
   1892       1.1     pooka 	if (sc->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
   1893       1.1     pooka 		error = EBUSY;
   1894       1.1     pooka 		goto bad;
   1895       1.1     pooka 	}
   1896       1.1     pooka 
   1897       1.1     pooka 	if (sc->sc_dk.dk_openmask != 0) {
   1898       1.1     pooka 		/*
   1899       1.1     pooka 		 * If any partition is open, but the disk has been invalidated,
   1900       1.1     pooka 		 * disallow further opens.
   1901       1.1     pooka 		 */
   1902       1.1     pooka 		if ((sc->sc_flags & EFLASHF_LOADED) == 0) {
   1903       1.1     pooka 			error = EIO;
   1904       1.1     pooka 			goto bad;
   1905       1.1     pooka 		}
   1906       1.1     pooka 	} else {
   1907       1.1     pooka 		if ((sc->sc_flags & EFLASHF_LOADED) == 0) {
   1908       1.1     pooka 			sc->sc_flags |= EFLASHF_LOADED;
   1909       1.1     pooka 
   1910       1.1     pooka 			/* Load the partition info if not already loaded. */
   1911       1.1     pooka 			eflashgetdisklabel(sc);
   1912       1.1     pooka 		}
   1913       1.1     pooka 	}
   1914       1.1     pooka 
   1915       1.1     pooka 	/* Check that the partition exists. */
   1916       1.1     pooka 	if (part != RAW_PART &&
   1917       1.1     pooka 	    (part >= sc->sc_dk.dk_label->d_npartitions ||
   1918       1.1     pooka 	     sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
   1919       1.1     pooka 		error = ENXIO;
   1920       1.1     pooka 		goto bad;
   1921       1.1     pooka 	}
   1922       1.1     pooka 
   1923       1.1     pooka 	/* Insure only one open at a time. */
   1924       1.1     pooka 	switch (fmt) {
   1925       1.1     pooka 	case S_IFCHR:
   1926       1.1     pooka 		sc->sc_dk.dk_copenmask |= (1 << part);
   1927       1.1     pooka 		break;
   1928       1.1     pooka 	case S_IFBLK:
   1929       1.1     pooka 		sc->sc_dk.dk_bopenmask |= (1 << part);
   1930       1.1     pooka 		break;
   1931       1.1     pooka 	}
   1932       1.1     pooka 	sc->sc_dk.dk_openmask =
   1933       1.1     pooka 	    sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
   1934       1.1     pooka 
   1935       1.1     pooka 	mutex_exit(&sc->sc_dk.dk_openlock);
   1936       1.1     pooka 	return 0;
   1937       1.1     pooka 
   1938       1.1     pooka  bad:
   1939       1.1     pooka 	mutex_exit(&sc->sc_dk.dk_openlock);
   1940       1.1     pooka 	DEBUG_PRINT(("%s: eflashopen -> %d\n", device_xname(sc->sc_dev), error),
   1941       1.1     pooka 	    DEBUG_XFERS);
   1942       1.1     pooka 	return error;
   1943       1.1     pooka }
   1944       1.1     pooka 
   1945       1.1     pooka int
   1946       1.1     pooka eflashclose(dev_t dev, int flag, int fmt, struct lwp *l)
   1947       1.1     pooka {
   1948       1.1     pooka 	struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
   1949       1.1     pooka 	int part = EFLASHPART(dev);
   1950       1.1     pooka 
   1951       1.2   tsutsui 	DEBUG_PRINT(("eflashclose %" PRIx64 "\n", dev), DEBUG_FUNCS);
   1952       1.1     pooka 
   1953       1.1     pooka 	mutex_enter(&sc->sc_dk.dk_openlock);
   1954       1.1     pooka 
   1955       1.1     pooka 	switch (fmt) {
   1956       1.1     pooka 	case S_IFCHR:
   1957       1.1     pooka 		sc->sc_dk.dk_copenmask &= ~(1 << part);
   1958       1.1     pooka 		break;
   1959       1.1     pooka 	case S_IFBLK:
   1960       1.1     pooka 		sc->sc_dk.dk_bopenmask &= ~(1 << part);
   1961       1.1     pooka 		break;
   1962       1.1     pooka 	}
   1963       1.1     pooka 	sc->sc_dk.dk_openmask =
   1964       1.1     pooka 	    sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
   1965       1.1     pooka 
   1966       1.1     pooka 	if (sc->sc_dk.dk_openmask == 0) {
   1967       1.1     pooka 
   1968       1.1     pooka 		if (! (sc->sc_flags & EFLASHF_KLABEL))
   1969       1.1     pooka 			sc->sc_flags &= ~EFLASHF_LOADED;
   1970       1.1     pooka 
   1971       1.1     pooka         DEBUG_PRINT(("%s: eflashclose flg %x\n", device_xname(sc->sc_dev), sc->sc_flags),
   1972       1.1     pooka                     DEBUG_XFERS);
   1973       1.1     pooka 
   1974       1.1     pooka 	}
   1975       1.1     pooka 
   1976       1.1     pooka 	mutex_exit(&sc->sc_dk.dk_openlock);
   1977       1.1     pooka 	return 0;
   1978       1.1     pooka }
   1979       1.1     pooka 
   1980       1.1     pooka void
   1981       1.1     pooka eflashgetdefaultlabel(struct eflash_softc *sc, struct disklabel *lp)
   1982       1.1     pooka {
   1983       1.1     pooka 
   1984       1.1     pooka 	DEBUG_PRINT(("%s: eflashgetdefaultlabel\n", device_xname(sc->sc_dev)), DEBUG_FUNCS);
   1985       1.1     pooka 	memset(lp, 0, sizeof(struct disklabel));
   1986       1.1     pooka 
   1987       1.1     pooka 	lp->d_secsize = DEV_BSIZE;
   1988       1.1     pooka 	lp->d_ntracks = 1;
   1989       1.1     pooka 	lp->d_nsectors = sc->sc_capacity;
   1990       1.1     pooka 	lp->d_ncylinders = 1;
   1991       1.1     pooka 	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
   1992       1.1     pooka 
   1993      1.15  christos 	lp->d_type = DKTYPE_ST506; /* ?!? */
   1994       1.1     pooka 
   1995       1.1     pooka 	strncpy(lp->d_typename, ST506, 16);
   1996       1.1     pooka 	strncpy(lp->d_packname, "fictitious", 16);
   1997       1.1     pooka 	if (sc->sc_capacity > UINT32_MAX)
   1998       1.1     pooka 		lp->d_secperunit = UINT32_MAX;
   1999       1.1     pooka 	else
   2000       1.1     pooka 		lp->d_secperunit = sc->sc_capacity;
   2001       1.1     pooka 	lp->d_rpm = 3600;
   2002       1.1     pooka 	lp->d_interleave = 1;
   2003       1.1     pooka 	lp->d_flags = 0;
   2004       1.1     pooka 
   2005       1.1     pooka 	lp->d_partitions[RAW_PART].p_offset = 0;
   2006       1.1     pooka 	lp->d_partitions[RAW_PART].p_size =
   2007       1.1     pooka 	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
   2008       1.1     pooka 	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
   2009       1.1     pooka 	lp->d_npartitions = RAW_PART + 1;
   2010       1.1     pooka 
   2011       1.1     pooka 	lp->d_magic = DISKMAGIC;
   2012       1.1     pooka 	lp->d_magic2 = DISKMAGIC;
   2013       1.1     pooka 	lp->d_checksum = dkcksum(lp);
   2014       1.1     pooka }
   2015       1.1     pooka 
   2016       1.1     pooka /*
   2017       1.1     pooka  * Fabricate a default disk label, and try to read the correct one.
   2018       1.1     pooka  */
   2019       1.1     pooka void
   2020       1.1     pooka eflashgetdisklabel(struct eflash_softc *sc)
   2021       1.1     pooka {
   2022       1.1     pooka 	struct disklabel *lp = sc->sc_dk.dk_label;
   2023       1.1     pooka 	const char *errstring;
   2024       1.1     pooka 
   2025       1.1     pooka 	DEBUG_PRINT(("%s: eflashgetdisklabel\n",  device_xname(sc->sc_dev)), DEBUG_FUNCS);
   2026       1.1     pooka 
   2027       1.1     pooka 	memset(sc->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
   2028       1.1     pooka 
   2029       1.1     pooka 	eflashgetdefaultlabel(sc, lp);
   2030       1.1     pooka 
   2031       1.1     pooka #ifdef HAS_BAD144_HANDLING
   2032       1.1     pooka 	sc->sc_bio.badsect[0] = -1;
   2033       1.1     pooka #endif
   2034       1.1     pooka 
   2035       1.1     pooka     /* BUGBUG: maj==0?? why is this not EFLASHLABELDEV(??sc->sc_dev) */
   2036       1.1     pooka 	errstring = readdisklabel(MAKEEFLASHDEV(0, device_unit(sc->sc_dev),
   2037       1.1     pooka 				  RAW_PART), eflashstrategy, lp,
   2038       1.1     pooka 				  sc->sc_dk.dk_cpulabel);
   2039       1.1     pooka 	if (errstring) {
   2040       1.1     pooka 		printf("%s: %s\n", device_xname(sc->sc_dev), errstring);
   2041       1.1     pooka 		return;
   2042       1.1     pooka 	}
   2043       1.1     pooka 
   2044       1.1     pooka #if DEBUG
   2045       1.1     pooka     if (EFLASH_DEBUG(DEBUG_WRITES)) {
   2046       1.1     pooka         int i, n = sc->sc_dk.dk_label->d_npartitions;
   2047       1.1     pooka         printf("%s: %d parts\n", device_xname(sc->sc_dev), n);
   2048       1.1     pooka         for (i = 0; i < n; i++) {
   2049       1.1     pooka             printf("\t[%d]: t=%x s=%d o=%d\n", i,
   2050       1.1     pooka                    sc->sc_dk.dk_label->d_partitions[i].p_fstype,
   2051       1.1     pooka                    sc->sc_dk.dk_label->d_partitions[i].p_size,
   2052       1.1     pooka                    sc->sc_dk.dk_label->d_partitions[i].p_offset);
   2053       1.1     pooka         }
   2054       1.1     pooka     }
   2055       1.1     pooka #endif
   2056       1.1     pooka 
   2057       1.1     pooka #ifdef HAS_BAD144_HANDLING
   2058       1.1     pooka 	if ((lp->d_flags & D_BADSECT) != 0)
   2059       1.1     pooka 		bad144intern(sc);
   2060       1.1     pooka #endif
   2061       1.1     pooka }
   2062       1.1     pooka 
   2063       1.1     pooka void
   2064       1.1     pooka eflashperror(const struct eflash_softc *sc)
   2065       1.1     pooka {
   2066       1.1     pooka 	const char *devname = device_xname(sc->sc_dev);
   2067       1.1     pooka 	u_int32_t Status = sc->sc_bio.r_error;
   2068       1.1     pooka 
   2069       1.1     pooka 	printf("%s: (", devname);
   2070       1.1     pooka 
   2071       1.1     pooka 	if (Status == 0)
   2072       1.1     pooka 		printf("error not notified");
   2073      1.20       mrg 	else
   2074      1.20       mrg 		printf("status=x%x", Status);
   2075       1.1     pooka 
   2076       1.1     pooka 	printf(")\n");
   2077       1.1     pooka }
   2078       1.1     pooka 
   2079       1.1     pooka int
   2080       1.1     pooka eflashioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
   2081       1.1     pooka {
   2082       1.1     pooka 	struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
   2083       1.1     pooka 	int error = 0, s;
   2084       1.1     pooka 
   2085       1.1     pooka 	DEBUG_PRINT(("eflashioctl(%lx)\n",xfer), DEBUG_FUNCS);
   2086       1.1     pooka 
   2087       1.1     pooka 	if ((sc->sc_flags & EFLASHF_LOADED) == 0)
   2088       1.1     pooka 		return EIO;
   2089       1.1     pooka 
   2090      1.14  christos 	error = disk_ioctl(&sc->sc_dk, dev, xfer, addr, flag, l);
   2091       1.1     pooka 	if (error != EPASSTHROUGH)
   2092       1.1     pooka 		return (error);
   2093       1.1     pooka 
   2094       1.1     pooka 	switch (xfer) {
   2095       1.1     pooka #ifdef HAS_BAD144_HANDLING
   2096       1.1     pooka 	case DIOCSBAD:
   2097       1.1     pooka 		if ((flag & FWRITE) == 0)
   2098       1.1     pooka 			return EBADF;
   2099       1.1     pooka 		sc->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
   2100       1.1     pooka 		sc->sc_dk.dk_label->d_flags |= D_BADSECT;
   2101       1.1     pooka 		bad144intern(sc);
   2102       1.1     pooka 		return 0;
   2103       1.1     pooka #endif
   2104       1.1     pooka 
   2105       1.1     pooka 	case DIOCWDINFO:
   2106       1.1     pooka 	case DIOCSDINFO:
   2107       1.1     pooka 	{
   2108       1.1     pooka 		struct disklabel *lp;
   2109       1.1     pooka 
   2110       1.1     pooka 		if ((flag & FWRITE) == 0)
   2111       1.1     pooka 			return EBADF;
   2112       1.1     pooka 
   2113       1.1     pooka 		lp = (struct disklabel *)addr;
   2114       1.1     pooka 
   2115       1.1     pooka 		mutex_enter(&sc->sc_dk.dk_openlock);
   2116       1.1     pooka 		sc->sc_flags |= EFLASHF_LABELLING;
   2117       1.1     pooka 
   2118       1.1     pooka 		error = setdisklabel(sc->sc_dk.dk_label,
   2119       1.1     pooka 		    lp, /*sc->sc_dk.dk_openmask : */0,
   2120       1.1     pooka 		    sc->sc_dk.dk_cpulabel);
   2121       1.1     pooka 		if (error == 0) {
   2122       1.1     pooka 			if (xfer == DIOCWDINFO)
   2123       1.1     pooka 				error = writedisklabel(EFLASHLABELDEV(dev),
   2124       1.1     pooka 				    eflashstrategy, sc->sc_dk.dk_label,
   2125       1.1     pooka 				    sc->sc_dk.dk_cpulabel);
   2126       1.1     pooka 		}
   2127       1.1     pooka 
   2128       1.1     pooka 		sc->sc_flags &= ~EFLASHF_LABELLING;
   2129       1.1     pooka 		mutex_exit(&sc->sc_dk.dk_openlock);
   2130       1.1     pooka 		return error;
   2131       1.1     pooka 	}
   2132       1.1     pooka 
   2133       1.1     pooka 	case DIOCKLABEL:
   2134       1.1     pooka 		if (*(int *)addr)
   2135       1.1     pooka 			sc->sc_flags |= EFLASHF_KLABEL;
   2136       1.1     pooka 		else
   2137       1.1     pooka 			sc->sc_flags &= ~EFLASHF_KLABEL;
   2138       1.1     pooka 		return 0;
   2139       1.1     pooka 
   2140       1.1     pooka 	case DIOCWLABEL:
   2141       1.1     pooka 		if ((flag & FWRITE) == 0)
   2142       1.1     pooka 			return EBADF;
   2143       1.1     pooka 		if (*(int *)addr)
   2144       1.1     pooka 			sc->sc_flags |= EFLASHF_WLABEL;
   2145       1.1     pooka 		else
   2146       1.1     pooka 			sc->sc_flags &= ~EFLASHF_WLABEL;
   2147       1.1     pooka 		return 0;
   2148       1.1     pooka 
   2149       1.1     pooka 	case DIOCGDEFLABEL:
   2150       1.1     pooka 		eflashgetdefaultlabel(sc, (struct disklabel *)addr);
   2151       1.1     pooka 		return 0;
   2152       1.1     pooka 
   2153       1.1     pooka 	case DIOCCACHESYNC:
   2154       1.1     pooka 		return 0;
   2155       1.1     pooka 
   2156       1.1     pooka 	case DIOCGSTRATEGY:
   2157       1.1     pooka 	    {
   2158       1.1     pooka 		struct disk_strategy *dks = (void *)addr;
   2159       1.1     pooka 
   2160       1.1     pooka 		s = splbio();
   2161       1.1     pooka 		strlcpy(dks->dks_name, bufq_getstrategyname(sc->sc_q),
   2162       1.1     pooka 		    sizeof(dks->dks_name));
   2163       1.1     pooka 		splx(s);
   2164       1.1     pooka 		dks->dks_paramlen = 0;
   2165       1.1     pooka 
   2166       1.1     pooka 		return 0;
   2167       1.1     pooka 	    }
   2168       1.1     pooka 
   2169       1.1     pooka 	case DIOCSSTRATEGY:
   2170       1.1     pooka 	    {
   2171       1.1     pooka 		struct disk_strategy *dks = (void *)addr;
   2172       1.1     pooka 		struct bufq_state *new;
   2173       1.1     pooka 		struct bufq_state *old;
   2174       1.1     pooka 
   2175       1.1     pooka 		if ((flag & FWRITE) == 0) {
   2176       1.1     pooka 			return EBADF;
   2177       1.1     pooka 		}
   2178       1.1     pooka 		if (dks->dks_param != NULL) {
   2179       1.1     pooka 			return EINVAL;
   2180       1.1     pooka 		}
   2181       1.1     pooka 		dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
   2182       1.1     pooka 		error = bufq_alloc(&new, dks->dks_name,
   2183       1.1     pooka 		    BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
   2184       1.1     pooka 		if (error) {
   2185       1.1     pooka 			return error;
   2186       1.1     pooka 		}
   2187       1.1     pooka 		s = splbio();
   2188       1.1     pooka 		old = sc->sc_q;
   2189       1.1     pooka 		bufq_move(new, old);
   2190       1.1     pooka 		sc->sc_q = new;
   2191       1.1     pooka 		splx(s);
   2192       1.1     pooka 		bufq_free(old);
   2193       1.1     pooka 
   2194       1.1     pooka 		return 0;
   2195       1.1     pooka 	    }
   2196       1.1     pooka 
   2197       1.1     pooka 	default:
   2198       1.1     pooka         /* NB: we get a DIOCGWEDGEINFO, but nobody else handles it either */
   2199       1.1     pooka         DEBUG_PRINT(("eflashioctl: unsup x%lx\n", xfer), DEBUG_FUNCS);
   2200       1.1     pooka 		return ENOTTY;
   2201       1.1     pooka 	}
   2202       1.1     pooka }
   2203       1.1     pooka 
   2204       1.1     pooka int
   2205       1.1     pooka eflashsize(dev_t dev)
   2206       1.1     pooka {
   2207       1.1     pooka 	struct eflash_softc *sc;
   2208       1.1     pooka 	int part, omask;
   2209       1.1     pooka 	int size;
   2210       1.1     pooka 
   2211       1.1     pooka 	DEBUG_PRINT(("eflashsize\n"), DEBUG_FUNCS);
   2212       1.1     pooka 
   2213       1.1     pooka 	sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev));
   2214       1.1     pooka 	if (sc == NULL)
   2215       1.1     pooka 		return (-1);
   2216       1.1     pooka 
   2217       1.1     pooka 	part = EFLASHPART(dev);
   2218       1.1     pooka 	omask = sc->sc_dk.dk_openmask & (1 << part);
   2219       1.1     pooka 
   2220       1.1     pooka 	if (omask == 0 && eflashopen(dev, 0, S_IFBLK, NULL) != 0)
   2221       1.1     pooka 		return (-1);
   2222       1.1     pooka 	if (sc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
   2223       1.1     pooka 		size = -1;
   2224       1.1     pooka 	else
   2225       1.1     pooka 		size = sc->sc_dk.dk_label->d_partitions[part].p_size *
   2226       1.1     pooka 		    (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
   2227       1.1     pooka 	if (omask == 0 && eflashclose(dev, 0, S_IFBLK, NULL) != 0)
   2228       1.1     pooka 		return (-1);
   2229       1.1     pooka 	return (size);
   2230       1.1     pooka }
   2231       1.1     pooka 
   2232       1.1     pooka /*
   2233       1.1     pooka  * Dump core after a system crash.
   2234       1.1     pooka  */
   2235       1.1     pooka int
   2236       1.1     pooka eflashdump(dev_t dev, daddr_t blkno, void *va, size_t size)
   2237       1.1     pooka {
   2238       1.1     pooka     /* no we dont */
   2239       1.1     pooka     return (ENXIO);
   2240       1.1     pooka }
   2241       1.1     pooka 
   2242       1.1     pooka #ifdef HAS_BAD144_HANDLING
   2243       1.1     pooka /*
   2244       1.1     pooka  * Internalize the bad sector table.
   2245       1.1     pooka  */
   2246       1.1     pooka void
   2247       1.1     pooka bad144intern(struct eflash_softc *sc)
   2248       1.1     pooka {
   2249       1.1     pooka 	struct dkbad *bt = &sc->sc_dk.dk_cpulabel->bad;
   2250       1.1     pooka 	struct disklabel *lp = sc->sc_dk.dk_label;
   2251       1.1     pooka 	int i = 0;
   2252       1.1     pooka 
   2253       1.1     pooka 	DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
   2254       1.1     pooka 
   2255       1.1     pooka 	for (; i < NBT_BAD; i++) {
   2256       1.1     pooka 		if (bt->bt_bad[i].bt_cyl == 0xffff)
   2257       1.1     pooka 			break;
   2258       1.1     pooka 		sc->sc_bio.badsect[i] =
   2259       1.1     pooka 		    bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
   2260       1.1     pooka 		    (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
   2261       1.1     pooka 		    (bt->bt_bad[i].bt_trksec & 0xff);
   2262       1.1     pooka 	}
   2263       1.1     pooka 	for (; i < NBT_BAD+1; i++)
   2264       1.1     pooka 		sc->sc_bio.badsect[i] = -1;
   2265       1.1     pooka }
   2266       1.1     pooka #endif
   2267       1.1     pooka 
   2268       1.1     pooka static void
   2269       1.6  christos eflash_set_geometry(struct eflash_softc *sc)
   2270       1.1     pooka {
   2271       1.6  christos 	struct disk_geom *dg = &sc->sc_dk.dk_geom;
   2272       1.1     pooka 
   2273       1.6  christos 	memset(dg, 0, sizeof(*dg));
   2274       1.1     pooka 
   2275       1.6  christos 	dg->dg_secperunit = sc->sc_capacity;
   2276       1.6  christos 	dg->dg_secsize = DEV_BSIZE /* XXX 512? */;
   2277       1.6  christos 	dg->dg_nsectors = sc->sc_capacity;
   2278       1.6  christos 	dg->dg_ntracks = 1;
   2279       1.6  christos 	dg->dg_ncylinders = sc->sc_capacity;
   2280       1.1     pooka 
   2281       1.6  christos 	disk_set_info(sc->sc_dev, &sc->sc_dk, ST506);
   2282       1.1     pooka }
   2283