Ejemplo n.º 1
0
// mcd_SwitchOperationTo
// -----------------------------------------------------------------------------
/// Switch MCD id.
///
/// To be called when appliction switch to another t-falsh.
/// @param  mcdId is mcd device identification under dual t-flash mode.value is 0 or 1.
/// 
// =============================================================================
PUBLIC MCD_ERR_T mcd_SwitchOperationTo(MCD_CARD_ID mcdId)
{
    MCD_CONFIG_STRUCT_T* mcd_config = NULL;
    MCD_ERR_T mcd_err = MCD_ERR_NO;
    UINT32 config_id;
    MCD_CARD_ID card_id;
    
    card_id = mcdId;
    mcd_config = (MCD_CONFIG_STRUCT_T*)tgt_GetMcdConfig();   
    config_id = mcdId ==  MCD_CARD_ID_0 ?  0:1;
   
    mcd_WaitSemTFlash();
    if(MCD_CONFIG_CARD_TYPE_SPI == mcd_config->mcd_if[0].type && 
       MCD_CONFIG_CARD_TYPE_SPI == mcd_config->mcd_if[1].type)
    {
        mcd_err = mcd_spi_SwitchOperationTo(mcdId);        
        MCD_TRACE(MCD_INFO_TRC, 0, "mcd_SwitchOperationTo:spi switch.mcdId = %d, mcd_err = %d.",mcdId,mcd_err);
    }
    else
    {
        mcd_err = MCD_ERR_NO;
    }
    
    if(MCD_ERR_NO == mcd_err)
    {
        g_mcd_id = mcdId;
        MCD_TRACE(MCD_INFO_TRC, 0, "mcd_SwitchOperationTo:g_mcd_id = %d.",g_mcd_id);
        // al_HstSendEvent(0xdada0000|g_mcd_id);
    }
    mcd_ReleaseSemTFlash();
    
    return mcd_err;
}
Ejemplo n.º 2
0
PUBLIC MCD_ERR_T mcd_Close(MCD_CARD_ID mcdId)
{
    MCD_CONFIG_STRUCT_T* mcd_config = NULL;
    UINT32 config_id = 0;
    //MCD_ERR_T mcd_err[2]= {MCD_ERR_NO,MCD_ERR_NO};
    MCD_ERR_T mcd_err = MCD_ERR_NO;
    
    mcd_config = (MCD_CONFIG_STRUCT_T*)tgt_GetMcdConfig();
    config_id = mcdId == MCD_CARD_ID_0 ? 0:1;

    mcd_WaitSemTFlash();

    if(MCD_CONFIG_CARD_TYPE_SDMMC == mcd_config->mcd_if[config_id].type)
    {
        if(1 == g_IsOpen[config_id])
        {
             // hal_HstSendEvent(0xb10000b0);
            mcd_err = mcd_sdmmc_Close(); 
            // hal_HstSendEvent(0xb100b000 | mcd_err); 
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Close(%d):(sdmmc)mcd_err =  %d.",mcdId,mcd_err);
        }        
        else
        {
            // hal_HstSendEvent(0xb10000b1);
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Close(%d):g_IsOpen[%d] == 0 ",mcdId,config_id);
        }
    }
    else if(MCD_CONFIG_CARD_TYPE_SPI == mcd_config->mcd_if[config_id].type)
    {
        if(1 == g_IsOpen[config_id])
        {
            // hal_HstSendEvent(0xb20000b0);
            mcd_err =  mcd_spi_Close();
            // hal_HstSendEvent(0xb200b000 | mcd_err); 
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Close(%d):(spi)mcd_err =  %d.",mcdId,mcd_err);
        }
        else
        {
            // hal_HstSendEvent(0xb20000b1);
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Close(%d):g_IsOpen[%d] == 0 ",mcdId,config_id);
        }
    }
    else
    {
        mcd_err = MCD_ERR_NO_CARD;
    }
    if(mcd_err == MCD_ERR_NO)
    {
        g_IsOpen[config_id] = 0;
    }
    mcd_ReleaseSemTFlash();
    
    return mcd_err;//mcd_err[config_id];

}
Ejemplo n.º 3
0
// mcd_Read
// -----------------------------------------------------------------------------
/// Read using pattern mode.
/// @param startAddr: of the MMC memory block where the data
/// will be read
/// @param blockRd Pointer to the buffer where the data will be stored. Must be aligned 
/// on a 32 bits boundary.
/// @param size Number of bytes to read. Must be an interger multiple of the 
/// sector size of the card.
// =============================================================================
PUBLIC MCD_ERR_T mcd_Read(UINT32 startAddr, UINT8* blockRd, UINT32 size)
{
    MCD_CONFIG_STRUCT_T* mcd_config = NULL;
    UINT32 config_id = 0;
    UINT32 i;
    MCD_ERR_T mcd_err = MCD_ERR_NO;
    
    mcd_config = (MCD_CONFIG_STRUCT_T*)tgt_GetMcdConfig();
    
    mcd_WaitSemTFlash();
    config_id = g_mcd_id == MCD_CARD_ID_0 ? 0:1;
    
    if(0 ==  g_IsOpen[config_id] )
    {
        MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Read:g_IsOpen is 0,addr = 0x%x.",startAddr);
        mcd_ReleaseSemTFlash();
        return MCD_ERR_NO_CARD;
    }
    
    if(MCD_CONFIG_CARD_TYPE_SDMMC == mcd_config->mcd_if[config_id].type)
    {
        
        mcd_err = mcd_sdmmc_Read(startAddr, blockRd, size);
        MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Read:mult-block,config_id = %d,mcd_err =  %d,startAddr = 0x%x,size = 0x%x.",config_id,mcd_err,startAddr,size);
        
    }
    else if(MCD_CONFIG_CARD_TYPE_SPI == mcd_config->mcd_if[config_id].type)
    {
        for(i = 0;  i < (size/MCD_DEFUALT_BLOCK_SIZE); i++)
        {
            // hal_HstSendEvent(0xc0000000 | (startAddr + i*MCD_DEFUALT_BLOCK_SIZE));
            mcd_err = mcd_spi_Read((startAddr + i*MCD_DEFUALT_BLOCK_SIZE), (blockRd + i*MCD_DEFUALT_BLOCK_SIZE), MCD_DEFUALT_BLOCK_SIZE);
            if(MCD_ERR_NO != mcd_err)
            {
                break;
            }
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Read:sigle-block,config_id = %d,mcd_err =  %d,startAddr = 0x%x,512.",config_id,mcd_err,(startAddr + i*MCD_DEFUALT_BLOCK_SIZE));
        }
    }
    else
    {        
        mcd_err = MCD_ERR_NO_CARD;
    }
    
    if(MCD_ERR_NO != mcd_err)
    {
        MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Read:sigle-block,config_id = %d,mcd_err =  %d,startAddr = 0x%x,size = 0x%x.",config_id,mcd_err,startAddr,size);
        // hal_HstSendEvent(0xc00000e1);
        // hal_HstSendEvent(mcd_err);  
    }
    mcd_ReleaseSemTFlash();
    
    return mcd_err;
}
Ejemplo n.º 4
0
PUBLIC VOID mcd_LowPower(VOID)
{
       if((0 == g_IsOpen[0]) && (0 == g_IsOpen[1]))
        {
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_LowPower ok.");
            pmd_EnablePower(PMD_POWER_SDMMC, FALSE);
            mcd_delay(1638);                
        }
        else
        {
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_LowPower tflas card not close. t0 = %d, t1= %d.",g_IsOpen[0],g_IsOpen[1]);
        }

}
Ejemplo n.º 5
0
void
mcdstart(struct mcd_softc *sc)
{
	struct buf *bp;
	int s;

loop:
	s = splbio();

	if ((bp = bufq_get(sc->buf_queue)) == NULL) {
		/* Nothing to do. */
		sc->active = 0;
		splx(s);
		return;
	}

	/* Block found to process. */
	MCD_TRACE("start: found block bp=0x%p\n", bp);
	splx(s);

	/* Changed media? */
	if ((sc->flags & MCDF_LOADED) == 0) {
		MCD_TRACE("start: drive not valid%s", "\n");
		bp->b_error = EIO;
		biodone(bp);
		goto loop;
	}

	sc->active = 1;

	/* Instrumentation. */
	s = splbio();
	disk_busy(&sc->sc_dk);
	splx(s);

	sc->mbx.retry = MCD_RDRETRIES;
	sc->mbx.bp = bp;
	sc->mbx.blkno = bp->b_rawblkno;
	sc->mbx.nblk = bp->b_bcount / sc->blksize;
	sc->mbx.sz = sc->blksize;
	sc->mbx.skip = 0;
	sc->mbx.state = MCD_S_BEGIN;
	sc->mbx.mode = MCD_MD_COOKED;

	s = splbio();
	(void) mcdintr(sc);
	splx(s);
}
Ejemplo n.º 6
0
int
mcdclose(dev_t dev, int flag, int fmt, struct lwp *l)
{
	struct mcd_softc *sc = device_lookup_private(&mcd_cd, MCDUNIT(dev));
	int part = MCDPART(dev);
	
	MCD_TRACE("close: partition=%d\n", part);

	mutex_enter(&sc->sc_lock);

	switch (fmt) {
	case S_IFCHR:
		sc->sc_dk.dk_copenmask &= ~(1 << part);
		break;
	case S_IFBLK:
		sc->sc_dk.dk_bopenmask &= ~(1 << part);
		break;
	}
	sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;

	if (sc->sc_dk.dk_openmask == 0) {
		/* XXXX Must wait for I/O to complete! */

#if 0
		(void) mcd_setmode(sc, MCD_MD_SLEEP);
#endif
		(void) mcd_setlock(sc, MCD_LK_UNLOCK);
	}

	mutex_exit(&sc->sc_lock);
	return 0;
}
Ejemplo n.º 7
0
PUBLIC MCD_ERR_T mcd_Open(MCD_CARD_ID mcdId,MCD_CSD_T* mcdCsd, MCD_CARD_VER mcdVer)
{
    MCD_CONFIG_STRUCT_T* mcd_config = NULL;
    UINT32 config_id = 0;
    MCD_ERR_T mcd_err = MCD_ERR_NO;
    
    mcd_config = (MCD_CONFIG_STRUCT_T*)tgt_GetMcdConfig();
    config_id = (mcdId == MCD_CARD_ID_0) ? 0:1;
    mcd_WaitSemTFlash();
    g_mcd_id = mcdId;
    
    if(MCD_CONFIG_CARD_TYPE_SDMMC == mcd_config->mcd_if[config_id].type)
    {
        if(0 == g_IsOpen[config_id])
        {
            //   hal_HstSendEvent(0xa10000a0);
            mcd_err = mcd_sdmmc_Open(mcdCsd,mcdVer,&mcd_config->mcd_if[config_id]);
            //    hal_HstSendEvent(0xa100a000 | mcd_err); 
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Open(%d):(sdmmc)mcd_err =  %d.",mcdId,mcd_err);
        }
        
    }
    else if(MCD_CONFIG_CARD_TYPE_SPI == mcd_config->mcd_if[config_id].type)
    {
        if(0 == g_IsOpen[config_id])
        {        
           // hal_HstSendEvent(0xa20000a0);
            mcd_err = mcd_spi_Open(mcdCsd,mcdVer,&mcd_config->mcd_if[config_id]);
		
            //hal_HstSendEvent(0xa200a000 | mcd_err); 
            MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Open(%d):(spi)mcd_err =  %d.",mcdId,mcd_err);
        }
    }
    else
    {
        mcd_err = MCD_ERR_NO_CARD;
    }
    
    if(MCD_ERR_NO == mcd_err)
    {
        g_IsOpen[config_id] = 1;
    }
    MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Open():config_id = %d,mcd_err =  %d,mcdVer = %d.",config_id,mcd_err,mcdVer);
    mcd_ReleaseSemTFlash();
   
    return mcd_err;
}
Ejemplo n.º 8
0
Archivo: mcd.c Proyecto: MarginC/kame
static int
mcd_setflags(struct mcd_softc *sc)
{

	/* check flags */
	if (    (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN))
	    || !(sc->data.status & MCDDSKIN)) {
		MCD_TRACE("setflags: sensed DSKCHNG or DOOROPEN or !DSKIN\n");
		mcd_soft_reset(sc);
		return (-1);
	}

	if (sc->data.status & MCDAUDIOBSY)
		sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS;
	else if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS)
		sc->data.audio_status = CD_AS_PLAY_COMPLETED;
	return (0);
}
Ejemplo n.º 9
0
// mcd_GetCardSize
// -----------------------------------------------------------------------------
/// Get card size
///
/// @param size Structure use to store size of memory card
// =============================================================================
PUBLIC MCD_ERR_T mcd_GetCardSize(MCD_CARD_SIZE_T* size)
{
    MCD_CONFIG_STRUCT_T* mcd_config = NULL;
    MCD_CARD_SIZE_T mcd_size = {0,0};
    UINT32 config_id = 0;
    MCD_ERR_T mcd_err = MCD_ERR_NO;   
    
    mcd_config = (MCD_CONFIG_STRUCT_T*)tgt_GetMcdConfig();
    
    mcd_WaitSemTFlash();
    config_id = g_mcd_id == MCD_CARD_ID_0 ? 0:1;
    
    if(MCD_CONFIG_CARD_TYPE_SDMMC == mcd_config->mcd_if[config_id].type)
    {
        mcd_err = mcd_sdmmc_GetCardSize(&mcd_size);
        // hal_HstSendEvent(0xba000000 | mcd_err);
        // hal_HstSendEvent(size->nbBlock);
    }
    else if(MCD_CONFIG_CARD_TYPE_SPI == mcd_config->mcd_if[config_id].type)
    {
        mcd_err = mcd_spi_GetCardSize(&mcd_size);
        
        // hal_HstSendEvent(0xbb000000 | mcd_err);
        // hal_HstSendEvent(size->nbBlock);
    }
    else
    {
        mcd_err = MCD_ERR_NO_CARD;
    }
    size->nbBlock = ((mcd_size.nbBlock/512)*mcd_size.blockLen);
    size->blockLen = mcd_size.blockLen > 0 ?512:0;
    MCD_TRACE(MCD_INFO_TRC, 0, "mcd_GetCardSize():config_id = %d,mcd_err =  %d,blk_nr = 0x%x,blk_sz = 0x%x.",config_id,mcd_err,size->nbBlock,size->blockLen);
    mcd_ReleaseSemTFlash();
    
    return mcd_err;
}
Ejemplo n.º 10
0
PUBLIC MCD_ERR_T mcd_Close(VOID)
{
    MCD_CONFIG_STRUCT_T* mcd_config = NULL;
    UINT32 config_id = 0;
    MCD_ERR_T mcd_err = MCD_ERR_NO;
    
    mcd_config = (MCD_CONFIG_STRUCT_T*)tgt_GetMcdConfig();
   
    mcd_WaitSemTFlash();
    if(MCD_CONFIG_CARD_TYPE_SDMMC == mcd_config->mcd_if[config_id].type)
    {
        if(1 == g_IsOpen)
        {
            mcd_err = mcd_sdmmc_Close();
        }
    }
    else if(MCD_CONFIG_CARD_TYPE_SPI == mcd_config->mcd_if[config_id].type)
    {
        if(1 == g_IsOpen)
        {
            mcd_err = mcd_spi_Close();
        }
    }
    else
    {
        mcd_err = MCD_ERR_NO_CARD;
    }
    
    if(MCD_ERR_NO == mcd_err)
    {
        g_IsOpen = 0;
    }
    MCD_TRACE(MCD_INFO_TRC, 0, "mcd_Close():config_id = %d,mcd_err =  %d.",config_id,mcd_err);
    mcd_ReleaseSemTFlash();
    return mcd_err;
}
Ejemplo n.º 11
0
Archivo: mcd.c Proyecto: MarginC/kame
static void
mcd_doread(struct mcd_softc *sc, int state, struct mcd_mbx *mbxin)
{
	struct mcd_mbx *mbx;
	struct bio *bp;
	int rm, i, k;
	struct mcd_read2 rbuf;
	int blknum;
	caddr_t	addr;

	mbx = (state!=MCD_S_BEGIN) ? sc->ch_mbxsave : mbxin;
	bp = mbx->bp;

loop:
	switch (state) {
	case MCD_S_BEGIN:
		mbx = sc->ch_mbxsave = mbxin;

	case MCD_S_BEGIN1:
retry_status:
		/* get status */
		MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDGETSTAT);
		mbx->count = RDELAY_WAITSTAT;
		sc->ch_state = MCD_S_WAITSTAT;
		sc->ch = timeout(mcd_timeout, (caddr_t)sc, hz/100); /* XXX */
		return;
	case MCD_S_WAITSTAT:
		sc->ch_state = MCD_S_WAITSTAT;
		untimeout(mcd_timeout,(caddr_t)sc, sc->ch);
		if (mbx->count-- >= 0) {
			if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) {
				sc->ch_state = MCD_S_WAITSTAT;
				timeout(mcd_timeout, (caddr_t)sc, hz/100); /* XXX */
				return;
			}
			sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF;
			if (sc->data.status & MCD_ST_CMDCHECK)
				goto retry_status;
			if (mcd_setflags(sc) < 0)
				goto changed;
			MCD_TRACE("got WAITSTAT delay=%d\n",
				RDELAY_WAITSTAT-mbx->count);
			/* reject, if audio active */
			if (sc->data.status & MCDAUDIOBSY) {
				device_printf(sc->dev, "audio is active\n");
				goto readerr;
			}

retry_mode:
			/* to check for raw/cooked mode */
			if (sc->data.flags & MCDREADRAW) {
				rm = MCD_MD_RAW;
				mbx->sz = MCDRBLK;
			} else {
				rm = MCD_MD_COOKED;
				mbx->sz = sc->data.blksize;
			}

			if (rm == sc->data.curr_mode)
				goto modedone;

			mbx->count = RDELAY_WAITMODE;

			sc->data.curr_mode = MCD_MD_UNKNOWN;
			mbx->mode = rm;
			MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSETMODE);
			MCD_WRITE(sc, MCD_REG_COMMAND, rm);

			sc->ch_state = MCD_S_WAITMODE;
			sc->ch = timeout(mcd_timeout, (caddr_t)sc, hz/100); /* XXX */
			return;
		} else {
			device_printf(sc->dev, "timeout getstatus\n");
			goto readerr;
		}

	case MCD_S_WAITMODE:
		sc->ch_state = MCD_S_WAITMODE;
		untimeout(mcd_timeout, (caddr_t)sc, sc->ch);
		if (mbx->count-- < 0) {
			device_printf(sc->dev, "timeout set mode\n");
			goto readerr;
		}
		if (MCD_READ(sc, MCD_FLAGS) & MFL_STATUS_NOT_AVAIL) {
			sc->ch_state = MCD_S_WAITMODE;
			sc->ch = timeout(mcd_timeout, (caddr_t)sc, hz/100);
			return;
		}
		sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF;
		if (sc->data.status & MCD_ST_CMDCHECK) {
			sc->data.curr_mode = MCD_MD_UNKNOWN;
			goto retry_mode;
		}
		if (mcd_setflags(sc) < 0)
			goto changed;
		sc->data.curr_mode = mbx->mode;
		MCD_TRACE("got WAITMODE delay=%d\n",
			RDELAY_WAITMODE-mbx->count);
modedone:
		/* for first block */
		mbx->nblk = (bp->bio_bcount + (mbx->sz-1)) / mbx->sz;
		mbx->skip = 0;

nextblock:
		blknum 	= (bp->bio_blkno / (mbx->sz/DEV_BSIZE))
			+ mbx->skip/mbx->sz;

		MCD_TRACE("mcd_doread: read blknum=%d for bp=%p\n",
			blknum, bp);

		/* build parameter block */
		hsg2msf(blknum,rbuf.start_msf);
retry_read:
		/* send the read command */
		critical_enter();
		MCD_WRITE(sc, MCD_REG_COMMAND, sc->data.read_command);
		MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[0]);
		MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[1]);
		MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[2]);
		MCD_WRITE(sc, MCD_REG_COMMAND, 0);
		MCD_WRITE(sc, MCD_REG_COMMAND, 0);
		MCD_WRITE(sc, MCD_REG_COMMAND, 1);
		critical_exit();

		/* Spin briefly (<= 2ms) to avoid missing next block */
		for (i = 0; i < 20; i++) {
			k = MCD_READ(sc, MCD_FLAGS);
			if (!(k & MFL_DATA_NOT_AVAIL))
				goto got_it;
			DELAY(100);
		}

		mbx->count = RDELAY_WAITREAD;
		sc->ch_state = MCD_S_WAITREAD;
		sc->ch = timeout(mcd_timeout, (caddr_t)sc, hz/100); /* XXX */
		return;
	case MCD_S_WAITREAD:
		sc->ch_state = MCD_S_WAITREAD;
		untimeout(mcd_timeout, (caddr_t)sc, sc->ch);
		if (mbx->count-- > 0) {
			k = MCD_READ(sc, MCD_FLAGS);
			if (!(k & MFL_DATA_NOT_AVAIL)) { /* XXX */
				MCD_TRACE("got data delay=%d\n",
					RDELAY_WAITREAD-mbx->count);
			got_it:
				/* data is ready */
				addr	= bp->bio_data + mbx->skip;

				MCD_WRITE(sc, MCD_REG_CTL2,0x04);	/* XXX */
				for (i=0; i<mbx->sz; i++)
					*addr++ = MCD_READ(sc, MCD_REG_RDATA);
				MCD_WRITE(sc, MCD_REG_CTL2,0x0c);	/* XXX */

				k = MCD_READ(sc, MCD_FLAGS);
				/* If we still have some junk, read it too */
				if (!(k & MFL_DATA_NOT_AVAIL)) {
					MCD_WRITE(sc, MCD_REG_CTL2, 0x04);       /* XXX */
					(void)MCD_READ(sc, MCD_REG_RDATA);
					(void)MCD_READ(sc, MCD_REG_RDATA);
					MCD_WRITE(sc, MCD_REG_CTL2, 0x0c);       /* XXX */
				}

				if (--mbx->nblk > 0) {
					mbx->skip += mbx->sz;
					goto nextblock;
				}

				/* return buffer */
				bp->bio_resid = 0;
				biodone(bp);

				sc->data.flags &= ~(MCDMBXBSY|MCDREADRAW);
				mcd_start(sc);
				return;
			}
			if (!(k & MFL_STATUS_NOT_AVAIL)) {
				sc->data.status = MCD_READ(sc, MCD_REG_STATUS) & 0xFF;
				if (sc->data.status & MCD_ST_CMDCHECK)
					goto retry_read;
				if (mcd_setflags(sc) < 0)
					goto changed;
			}
			sc->ch_state = MCD_S_WAITREAD;
			sc->ch = timeout(mcd_timeout, (caddr_t)sc, hz/100); /* XXX */
			return;
		} else {
			device_printf(sc->dev, "timeout read data\n");
			goto readerr;
		}
	}

readerr:
	if (mbx->retry-- > 0) {
		device_printf(sc->dev, "retrying\n");
		state = MCD_S_BEGIN1;
		goto loop;
	}
harderr:
	/* invalidate the buffer */
	bp->bio_flags |= BIO_ERROR;
	bp->bio_resid = bp->bio_bcount;
	biodone(bp);

	sc->data.flags &= ~(MCDMBXBSY|MCDREADRAW);
	mcd_start(sc);
	return;

changed:
	device_printf(sc->dev, "media changed\n");
	goto harderr;

#ifdef NOTDEF
	device_printf(sc->dev, "unit timeout, resetting\n");
	MCD_WRITE(sc, MCD_REG_RESET, MCD_CMDRESET);
	DELAY(300000);
	(void)mcd_getstat(sc, 1);
	(void)mcd_getstat(sc, 1);
	/*sc->data.status &= ~MCDDSKCHNG; */
	sc->data.debug = 1; /* preventive set debug mode */

#endif

}
Ejemplo n.º 12
0
Archivo: mcd.c Proyecto: MarginC/kame
static int
mcdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
{
	struct mcd_softc *sc;
	int retry,r;

	sc = (struct mcd_softc *)dev->si_drv1;

	if (mcd_getstat(sc, 1) == -1) /* detect disk change too */
		return (EIO);
MCD_TRACE("ioctl called 0x%lx\n", cmd);

	switch (cmd) {
	case CDIOCSETPATCH:
	case CDIOCGETVOL:
	case CDIOCSETVOL:
	case CDIOCSETMONO:
	case CDIOCSETSTERIO:
	case CDIOCSETMUTE:
	case CDIOCSETLEFT:
	case CDIOCSETRIGHT:
		return (EINVAL);
	case CDIOCEJECT:
		return mcd_eject(sc);
	case CDIOCSETDEBUG:
		sc->data.debug = 1;
		return (0);
	case CDIOCCLRDEBUG:
		sc->data.debug = 0;
		return (0);
	case CDIOCRESET:
		return mcd_hard_reset(sc);
	case CDIOCALLOW:
		return mcd_lock_door(sc, MCD_LK_UNLOCK);
	case CDIOCPREVENT:
		return mcd_lock_door(sc, MCD_LK_LOCK);
	case CDIOCCLOSE:
		return mcd_inject(sc);
	}

	if (!(sc->data.flags & MCDVALID)) {
		if (    (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN))
		    || !(sc->data.status & MCDDSKIN))
			for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) {
				(void) tsleep((caddr_t)sc, PSOCK | PCATCH, "mcdsn2", hz/WAIT_FRAC);
				if ((r = mcd_getstat(sc, 1)) == -1)
					return (EIO);
				if (r != -2)
					break;
			}
		if (   (sc->data.status & (MCDDOOROPEN|MCDDSKCHNG))
		    || !(sc->data.status & MCDDSKIN)
		    || mcdsize(dev) < 0
		   )
			return (ENXIO);
		sc->data.flags |= MCDVALID;
		sc->data.partflags |= MCDREADRAW;
		(void) mcd_lock_door(sc, MCD_LK_LOCK);
		if (!(sc->data.flags & MCDVALID))
			return (ENXIO);
	}

	switch (cmd) {
	case DIOCGMEDIASIZE:
		*(off_t *)addr = (off_t)sc->data.disksize * sc->data.blksize;
		return (0);
		break;
	case DIOCGSECTORSIZE:
		*(u_int *)addr = sc->data.blksize;
		return (0);
		break;

	case CDIOCPLAYTRACKS:
		return mcd_playtracks(sc, (struct ioc_play_track *) addr);
	case CDIOCPLAYBLOCKS:
		return mcd_playblocks(sc, (struct ioc_play_blocks *) addr);
	case CDIOCPLAYMSF:
		return mcd_playmsf(sc, (struct ioc_play_msf *) addr);
	case CDIOCREADSUBCHANNEL:
		return mcd_subchan(sc, (struct ioc_read_subchannel *) addr);
	case CDIOREADTOCHEADER:
		return mcd_toc_header(sc, (struct ioc_toc_header *) addr);
	case CDIOREADTOCENTRYS:
		return mcd_toc_entrys(sc, (struct ioc_read_toc_entry *) addr);
	case CDIOCRESUME:
		return mcd_resume(sc);
	case CDIOCPAUSE:
		return mcd_pause(sc);
	case CDIOCSTART:
		if (mcd_setmode(sc, MCD_MD_COOKED) != 0)
			return (EIO);
		return (0);
	case CDIOCSTOP:
		return mcd_stop(sc);
	default:
		return (ENOTTY);
	}
	/*NOTREACHED*/
}
Ejemplo n.º 13
0
int
mcdopen(dev_t dev, int flag, int fmt, struct lwp *l)
{
	int error, part;
	struct mcd_softc *sc;

	sc = device_lookup_private(&mcd_cd, MCDUNIT(dev));
	if (sc == NULL)
		return ENXIO;

	mutex_enter(&sc->sc_lock);

	if (sc->sc_dk.dk_openmask != 0) {
		/*
		 * If any partition is open, but the disk has been invalidated,
		 * disallow further opens.
		 */
		if ((sc->flags & MCDF_LOADED) == 0) {
			error = EIO;
			goto bad3;
		}
	} else {
		/*
		 * Lock the drawer.  This will also notice any pending disk
		 * change or door open indicator and clear the MCDF_LOADED bit
		 * if necessary.
		 */
		(void) mcd_setlock(sc, MCD_LK_LOCK);

		if ((sc->flags & MCDF_LOADED) == 0) {
			/* Partially reset the state. */
			sc->lastmode = MCD_MD_UNKNOWN;
			sc->lastupc = MCD_UPC_UNKNOWN;

			sc->flags |= MCDF_LOADED;

			/* Set the mode, causing the disk to spin up. */
			if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
				goto bad2;

			/* Load the physical device parameters. */
			if (mcd_get_parms(sc) != 0) {
				error = ENXIO;
				goto bad2;
			}

			/* Read the table of contents. */
			if ((error = mcd_read_toc(sc)) != 0)
				goto bad2;

			/* Fabricate a disk label. */
			mcdgetdisklabel(sc);
		}
	}

	part = MCDPART(dev);

	MCD_TRACE("open: partition=%d disksize=%ld blksize=%d\n", part,
	    sc->disksize, sc->blksize);

	/* Check that the partition exists. */
	if (part != RAW_PART &&
	    (part >= sc->sc_dk.dk_label->d_npartitions ||
	     sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
		error = ENXIO;
		goto bad;
	}

	/* Insure only one open at a time. */
	switch (fmt) {
	case S_IFCHR:
		sc->sc_dk.dk_copenmask |= (1 << part);
		break;
	case S_IFBLK:
		sc->sc_dk.dk_bopenmask |= (1 << part);
		break;
	}
	sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;

	mutex_exit(&sc->sc_lock);
	return 0;

bad2:
	sc->flags &= ~MCDF_LOADED;

bad:
	if (sc->sc_dk.dk_openmask == 0) {
#if 0
		(void) mcd_setmode(sc, MCD_MD_SLEEP);
#endif
		(void) mcd_setlock(sc, MCD_LK_UNLOCK);
	}

bad3:
	mutex_exit(&sc->sc_lock);
	return error;
}
Ejemplo n.º 14
0
int
mcdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
{
	struct mcd_softc *sc = device_lookup_private(&mcd_cd, MCDUNIT(dev));
	int error;
	int part;
#ifdef __HAVE_OLD_DISKLABEL
	struct disklabel newlabel;
#endif
	
	MCD_TRACE("ioctl: cmd=0x%lx\n", cmd);

	if ((sc->flags & MCDF_LOADED) == 0)
		return EIO;

	error = disk_ioctl(&sc->sc_dk, dev, cmd, addr, flag, l);
	if (error != EPASSTHROUGH)
		return error;

	part = MCDPART(dev);
	switch (cmd) {
	case DIOCWDINFO:
	case DIOCSDINFO:
#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCWDINFO:
	case ODIOCSDINFO:
#endif
	{
		struct disklabel *lp;

		if ((flag & FWRITE) == 0)
			return EBADF;

#ifdef __HAVE_OLD_DISKLABEL
		if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
			memset(&newlabel, 0, sizeof newlabel);
			memcpy(&newlabel, addr, sizeof (struct olddisklabel));
			lp = &newlabel;
		} else
#endif
		lp = addr;

		mutex_enter(&sc->sc_lock);
		sc->flags |= MCDF_LABELLING;

		error = setdisklabel(sc->sc_dk.dk_label,
		    lp, /*sc->sc_dk.dk_openmask : */0,
		    sc->sc_dk.dk_cpulabel);
		if (error == 0) {
		}

		sc->flags &= ~MCDF_LABELLING;
		mutex_exit(&sc->sc_lock);
		return error;
	}

	case DIOCWLABEL:
		return EBADF;

	case DIOCGDEFLABEL:
		mcdgetdefaultlabel(sc, addr);
		return 0;

#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCGDEFLABEL:
		mcdgetdefaultlabel(sc, &newlabel);
		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
			return ENOTTY;
		memcpy(addr, &newlabel, sizeof (struct olddisklabel));
		return 0;
#endif

	case CDIOCPLAYTRACKS:
		return mcd_playtracks(sc, addr);
	case CDIOCPLAYMSF:
		return mcd_playmsf(sc, addr);
	case CDIOCPLAYBLOCKS:
		return mcd_playblocks(sc, addr);
	case CDIOCREADSUBCHANNEL: {
		struct cd_sub_channel_info info;
		error = mcd_read_subchannel(sc, addr, &info);
		if (error != 0) {
			struct ioc_read_subchannel *ch = addr;
			error = copyout(&info, ch->data, ch->data_len);
		}
		return error;
	}
	case CDIOCREADSUBCHANNEL_BUF:
		return mcd_read_subchannel(sc, addr,
		    &((struct ioc_read_subchannel_buf *)addr)->info);
	case CDIOREADTOCHEADER:
		return mcd_toc_header(sc, addr);
	case CDIOREADTOCENTRYS: {
		struct cd_toc_entry entries[MCD_MAXTOCS];
		struct ioc_read_toc_entry *te = addr;
		int count;
		if (te->data_len > sizeof entries)
			return EINVAL;
		error = mcd_toc_entries(sc, te, entries, &count);
		if (error == 0)
			/* Copy the data back. */
			error = copyout(entries, te->data, min(te->data_len,
					count * sizeof(struct cd_toc_entry)));
		return error;
	}
	case CDIOREADTOCENTRIES_BUF: {
		struct ioc_read_toc_entry_buf *te = addr;
		int count;
		if (te->req.data_len > sizeof te->entry)
			return EINVAL;
		return mcd_toc_entries(sc, &te->req, te->entry, &count);
	}
	case CDIOCSETPATCH:
	case CDIOCGETVOL:
	case CDIOCSETVOL:
	case CDIOCSETMONO:
	case CDIOCSETSTEREO:
	case CDIOCSETMUTE:
	case CDIOCSETLEFT:
	case CDIOCSETRIGHT:
		return EINVAL;
	case CDIOCRESUME:
		return mcd_resume(sc);
	case CDIOCPAUSE:
		return mcd_pause(sc);
	case CDIOCSTART:
		return EINVAL;
	case CDIOCSTOP:
		return mcd_stop(sc);
	case DIOCEJECT:
		if (*(int *)addr == 0) {
			/*
			 * Don't force eject: check that we are the only
			 * partition open. If so, unlock it.
			 */
			if ((sc->sc_dk.dk_openmask & ~(1 << part)) == 0 &&
			    sc->sc_dk.dk_bopenmask + sc->sc_dk.dk_copenmask ==
			    sc->sc_dk.dk_openmask) {
				error = mcd_setlock(sc, MCD_LK_UNLOCK);
				if (error)
					return (error);
			} else {
				return (EBUSY);
			}
		}
		/* FALLTHROUGH */
	case CDIOCEJECT: /* FALLTHROUGH */
	case ODIOCEJECT:
		return mcd_eject(sc);
	case CDIOCALLOW:
		return mcd_setlock(sc, MCD_LK_UNLOCK);
	case CDIOCPREVENT:
		return mcd_setlock(sc, MCD_LK_LOCK);
	case DIOCLOCK:
		return mcd_setlock(sc,
		    (*(int *)addr) ? MCD_LK_LOCK : MCD_LK_UNLOCK);
	case CDIOCSETDEBUG:
		sc->debug = 1;
		return 0;
	case CDIOCCLRDEBUG:
		sc->debug = 0;
		return 0;
	case CDIOCRESET:
		return mcd_hard_reset(sc);

	default:
		return ENOTTY;
	}

#ifdef DIAGNOSTIC
	panic("mcdioctl: impossible");
#endif
}
Ejemplo n.º 15
0
void
mcdstrategy(struct buf *bp)
{
	struct mcd_softc *sc;
	struct disklabel *lp;
	daddr_t blkno;
	int s;

	sc = device_lookup_private(&mcd_cd, MCDUNIT(bp->b_dev));
	lp = sc->sc_dk.dk_label;

	/* Test validity. */
	MCD_TRACE("strategy: buf=0x%p blkno=%d bcount=%d\n", bp,
	    (int) bp->b_blkno, bp->b_bcount);
	if (bp->b_blkno < 0 ||
	    (bp->b_bcount % sc->blksize) != 0) {
		printf("%s: strategy: blkno = %" PRId64 " bcount = %d\n",
		    device_xname(sc->sc_dev), bp->b_blkno, bp->b_bcount);
		bp->b_error = EINVAL;
		goto done;
	}

	/* If device invalidated (e.g. media change, door open), error. */
	if ((sc->flags & MCDF_LOADED) == 0) {
		MCD_TRACE("strategy: drive not valid%s", "\n");
		bp->b_error = EIO;
		goto done;
	}

	/* No data to read. */
	if (bp->b_bcount == 0)
		goto done;

	/*
	 * Do bounds checking, adjust transfer. if error, process.
	 * If end of partition, just return.
	 */
	if (MCDPART(bp->b_dev) != RAW_PART &&
	    bounds_check_with_label(&sc->sc_dk, bp,
	    (sc->flags & (MCDF_WLABEL|MCDF_LABELLING)) != 0) <= 0)
		goto done;

	/*
	 * Now convert the block number to absolute and put it in
	 * terms of the device's logical block size.
	 */
	blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
	if (MCDPART(bp->b_dev) != RAW_PART)
		blkno += lp->d_partitions[MCDPART(bp->b_dev)].p_offset;

	bp->b_rawblkno = blkno;

	/* Queue it. */
	s = splbio();
	bufq_put(sc->buf_queue, bp);
	splx(s);
	if (!sc->active)
		mcdstart(sc);
	return;

done:
	bp->b_resid = bp->b_bcount;
	biodone(bp);
}
Ejemplo n.º 16
0
/*
 * State machine to process read requests.
 * Initialize with MCD_S_BEGIN: calculate sizes, and set mode
 * MCD_S_WAITMODE: waits for status reply from set mode, set read command
 * MCD_S_WAITREAD: wait for read ready, read data.
 */
int
mcdintr(void *arg)
{
	struct mcd_softc *sc = arg;
	struct mcd_mbx *mbx = &sc->mbx;
	struct buf *bp = mbx->bp;
	bus_space_tag_t iot = sc->sc_iot;
	bus_space_handle_t ioh = sc->sc_ioh;

	int i;
	u_char x;
	bcd_t msf[3];

	switch (mbx->state) {
	case MCD_S_IDLE:
		return 0;

	case MCD_S_BEGIN:
	tryagain:
		if (mbx->mode == sc->lastmode)
			goto firstblock;

		sc->lastmode = MCD_MD_UNKNOWN;
		bus_space_write_1(iot, ioh, MCD_COMMAND, MCD_CMDSETMODE);
		bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->mode);

		mbx->count = RDELAY_WAITMODE;
		mbx->state = MCD_S_WAITMODE;

	case MCD_S_WAITMODE:
		callout_stop(&sc->sc_pintr_ch);
		for (i = 20; i; i--) {
			x = bus_space_read_1(iot, ioh, MCD_XFER);
			if ((x & MCD_XF_STATUSUNAVAIL) == 0)
				break;
			delay(50);
		}
		if (i == 0)
			goto hold;
		sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
		mcd_setflags(sc);
		if ((sc->flags & MCDF_LOADED) == 0)
			goto changed;
		MCD_TRACE("doread: got WAITMODE delay=%d\n",
		    RDELAY_WAITMODE - mbx->count);

		sc->lastmode = mbx->mode;

	firstblock:
		MCD_TRACE("doread: read blkno=%d for bp=0x%p\n", 
		    (int) mbx->blkno, bp);

		/* Build parameter block. */
		hsg2msf(mbx->blkno, msf);

		/* Send the read command. */
		bus_space_write_1(iot, ioh, MCD_COMMAND, sc->readcmd);
		bus_space_write_1(iot, ioh, MCD_COMMAND, msf[0]);
		bus_space_write_1(iot, ioh, MCD_COMMAND, msf[1]);
		bus_space_write_1(iot, ioh, MCD_COMMAND, msf[2]);
		bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
		bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
		bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->nblk);

		mbx->count = RDELAY_WAITREAD;
		mbx->state = MCD_S_WAITREAD;

	case MCD_S_WAITREAD:
		callout_stop(&sc->sc_pintr_ch);
	nextblock:
	loop:
		for (i = 20; i; i--) {
			x = bus_space_read_1(iot, ioh, MCD_XFER);
			if ((x & MCD_XF_DATAUNAVAIL) == 0)
				goto gotblock;
			if ((x & MCD_XF_STATUSUNAVAIL) == 0)
				break;
			delay(50);
		}
		if (i == 0)
			goto hold;
		sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
		mcd_setflags(sc);
		if ((sc->flags & MCDF_LOADED) == 0)
			goto changed;
#if 0
		printf("%s: got status byte %02x during read\n",
		    device_xname(sc->sc_dev), (u_int)sc->status);
#endif
		goto loop;

	gotblock:
		MCD_TRACE("doread: got data delay=%d\n",
		    RDELAY_WAITREAD - mbx->count);

		/* Data is ready. */
		bus_space_write_1(iot, ioh, MCD_CTL2, 0x04);	/* XXX */
		bus_space_read_multi_1(iot, ioh, MCD_RDATA,
		    (char *)bp->b_data + mbx->skip, mbx->sz);
		bus_space_write_1(iot, ioh, MCD_CTL2, 0x0c);	/* XXX */
		mbx->blkno += 1;
		mbx->skip += mbx->sz;
		if (--mbx->nblk > 0)
			goto nextblock;

		mbx->state = MCD_S_IDLE;

		/* Return buffer. */
		bp->b_resid = 0;
		disk_unbusy(&sc->sc_dk, bp->b_bcount, (bp->b_flags & B_READ));
		biodone(bp);

		mcdstart(sc);
		return 1;

	hold:
		if (mbx->count-- < 0) {
			printf("%s: timeout in state %d",
			    device_xname(sc->sc_dev), mbx->state);
			goto readerr;
		}

#if 0
		printf("%s: sleep in state %d\n", device_xname(sc->sc_dev),
		    mbx->state);
#endif
		callout_reset(&sc->sc_pintr_ch, hz / 100,
		    mcd_pseudointr, sc);
		return -1;
	}

readerr:
	if (mbx->retry-- > 0) {
		printf("; retrying\n");
		goto tryagain;
	} else
		printf("; giving up\n");

changed:
	/* Invalidate the buffer. */
	bp->b_error = EIO;
	bp->b_resid = bp->b_bcount - mbx->skip;
	disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid),
	    (bp->b_flags & B_READ));
	biodone(bp);

	mcdstart(sc);
	return -1;

#ifdef notyet
	printf("%s: unit timeout; resetting\n", device_xname(sc->sc_dev));
	bus_space_write_1(iot, ioh, MCD_RESET, MCD_CMDRESET);
	delay(300000);
	(void) mcd_getstat(sc, 1);
	(void) mcd_getstat(sc, 1);
	/*sc->status &= ~MCD_ST_DSKCHNG; */
	sc->debug = 1; /* preventive set debug mode */
#endif
}