NTLK [Help] PCMCIA controllers & other informations

From: Paul Guyot (pguyot@pnm-consulting.com)
Date: Fri Jun 23 2000 - 06:13:39 CDT


Hi all,

Here is the situation: I send the identify command in memory mode to
the card. I do that on both a MP120 and a MP2100.
The current code is below.
The problem is that the card answers properly (i.e. says it is a
CompactFlash card) only if I do a restart just before issuing the
command. I don't know how to send two consecutive and successful
commands to the card. I believe it is a timing problem, but I don't
really know what to do.

I have disassembled parts of the ROM including the non working ATA
driver (which does not succeed with the identify command), and the
socket API (on both MPs).

Hence it would really help if I had the specs of the PCMCIA
controllers to know exactly what functions do what with the socket
pins and signals.
Does anyone know what's the PCMCIA socket controller for the MP120?
Can anyone point me to CL-PS7030's documentation or the MP120's
controller documentation?

I should say that there is little or no documentation concerning the
cards and the sockets. I really wonder why it does not work, and what
to do, and I am getting tired of all this useless wrong guesses.
Hence my call for help.

Here is the code and the logs on both computers. (now I know how to
generate the high ROM MP120 image for Hammer). This function is
called when the InstallService function of the card handler is
called, hence the OS may have done things to the card. (besides, I am
on a separated preemptive thread).
I don't understand why the card does not say it is ready after a
reset (this may be the problem?), or what really happens with the
buffers and the access I have to them and the card has to them. I
don't know what the control flags of the socket API do.

Besides, there is in the NE2000 sample a reference to a bug in the
PCMCIA for 8 bits exchanges, saying that this hasn't been fixed by a
system patch yet. What's the real state of that?
Anyway, I believed first it was the problem, but it seems that it
isn't. Indeed, the identify command works.

<code>

VccOn( (int) mSocket->SocketNumber() );
// The compact flash card accepts vcc (i.e. 3.3-5 V), and does not
require 12 V.

TDelayTimer myDelayTimer;
ULong timeout = 0;

volatile TCardConfigRegs* myCardConfigRegs = (TCardConfigRegs*)
(mSocket->AttributeMemBaseAddr()
  + mCard->fRegisterBaseAddress);
// TCardConfigRegs is a structure defined in Apple's headers which
allows to access the config registers in attribute memory with big to
little endian conversion.

ULong lastReset;

ULong theSavedControl = mSocket->GetControl();

mSocket->SetDefaultSpeeds();

// ::printf( "Common Mem Speed: %i\n", mSocket->GetCommonMemSpeed() );
// mSocket->SetAttributeMemSpeed( 12000 ); // PCMCIA default, 12 Ás
// mSocket->SetCommonMemSpeed( 12000 ); // PCMCIA default, 12 Ás
// mSocket->SetIOSpeed( 12000 ); // PCMCIA default, 12 Ás
// ::printf( "Common Mem Speed, again: %i\n", mSocket->GetCommonMemSpeed() );

// Changing the speeds doesn't help. Besides, it does not say 12000
after I change it to that, but 2816 or something like that which I
believe to be the max.

int i, j, l, m, n, k;
// Those are for loops to do various accesses with different parameters.
// Some are unused with this code version. (I did 20 timing different
codes to get the proper configuration).

ULong* myBufferAsLong = (ULong*) outBuffer;

ULong controls[16];
controls[0] = 0;
controls[1] = kCardAssembly32;
controls[2] = kCardByteAccess;
controls[3] = kCardByteAccess | kCardAssembly32;
controls[4] = kCardPortAccess;
controls[5] = kCardPortAccess | kCardAssembly32;
controls[6] = kCardPortAccess | kCardByteAccess;
controls[7] = kCardPortAccess | kCardByteAccess | kCardAssembly32;
controls[8] = kCareAutoIncAddress;
controls[9] = kCareAutoIncAddress | kCardAssembly32;
controls[10] = kCareAutoIncAddress | kCardByteAccess;
controls[11] = kCareAutoIncAddress | kCardByteAccess | kCardAssembly32;
controls[12] = kCareAutoIncAddress | kCardPortAccess;
controls[13] = kCareAutoIncAddress | kCardPortAccess | kCardAssembly32;
controls[14] = kCareAutoIncAddress | kCardPortAccess | kCardByteAccess;
controls[15] = kCareAutoIncAddress | kCardPortAccess |
kCardByteAccess | kCardAssembly32;
// I only work with the flags allowed on the MP120. (the set control
function on that machine does a &0x1E; the set control function on
the MP2100 is more complex: it writes values at three places and not
one).
// I have discovered the role of the NoLittleEndian or something like
that flag (0x20)
// as one could guess, it inverts the bytes. Works with the
Do16ReadBit function which is Voyager only.

ULong lastOK = 0;

ULong wait[8];
// 8 levels of wait
wait[0] = 0; // don't wait
wait[1] = 0x40;
wait[2] = 0x80;
wait[3] = 0x400;
wait[4] = 0x800;
wait[5] = 0x4000;
wait[6] = 0x8000;
wait[7] = 0x40000;
// 8 values for different timeouts

for (k = 0; k <= 128; k++)
{
// k is for timeouts and the ATA reset.
// bits 0-2 (less significants) are for first wait time
// bits 3-5 for second wait time
// bit 6 is for ATA reset
  for (m = 0; m <= 20; m++)
  {
// I try to issue the command 21 times.
    mSocket->SetControl( theSavedControl );

    VccOn( (int) mSocket->SocketNumber() );
    timeout = 0;

    if (m == 0)
    {
// First time, I reset the card.

        myCardConfigRegs->fSocketAndCopyReg = (
         (mSocket->SocketNumber() & kCardSocketAndCopySocketNumber) );
// A/ the doc says the socket and copy register should be written prior to any
// change to the ConfigOptionReg. In fact, this does not change anything.
        ::ShortTimerDelay (0x40);

        myCardConfigRegs->fConfigOptionReg = (
         (mCardConfiguration->fConfigurationNumber &
kCardConfigOptionConfIndex)
          | kCardConfigOptionSReset );
// B/ maintain the reset flag on the ConfigOptionReg
// the configuration number is 0 (memory access)

        lastReset = myDelayTimer.GetHardwareTime();

        ::ShortTimerDelay (0x40);
// Even 0x800000 does not help. The doc says the signal should be
maintain the reset width.
// But I don't know what's the reset width. Anyone?

        myCardConfigRegs->fSocketAndCopyReg = (
         (mSocket->SocketNumber() & kCardSocketAndCopySocketNumber) );
// C/ like A
        ::ShortTimerDelay (0x40);

        myCardConfigRegs->fConfigOptionReg = (
         mCardConfiguration->fConfigurationNumber &
kCardConfigOptionConfIndex);
  // I should clear the reset flag.
        myDelayTimer.ResetTimeOut( 0x4000 );
        while ((mSocket->IsReady() == false) && ((timeout =
myDelayTimer.TimedOut()) == false));

        if (timeout)
        {
         timeout = 1;
        }
// I always timeout, i.e. the card is never ready. Gosh.
    }

    mSocket->SetControl( controls[6] );
// This works, like other configuration options.
// 6 means kCardPortAccess | kCardByteAccess

    if (WaitFor(wait[k & 0x7]))
    {
        timeout |= 2;
    }
// Waitfor returns -1 in case of timeout.
// WaitFor waits until the BSY bit of the ATA alternare status
register is cleared.
// Reading the status register (which is said to clear a pending
interrupt) does not work.

    if (k & 0x40)
    {
        mMemInterface->fAltStatus_DeviceControl = kDevCtlReg_ALWS
         | kDevCtlReg_SWRst | kDevCtlReg_IEn;

        ::ShortTimerDelay (0x40);

        mMemInterface->fAltStatus_DeviceControl = kDevCtlReg_ALWS
         | kDevCtlReg_IEn;

        ::ShortTimerDelay (0x40);
// This is an ATA reset and selects no Interrupt (default is with
interrupts). Does not change anything.
    }

    UChar statusWhenWritingCmd = mMemInterface->fStatus_Command;
// Normally, the card should say I am ready to get a command (0x50).
It in fact says 0x80, i.e. I am busy.
// When I read the AlternateStatus register instead, I get 00 for k <
0x40, 0A (i.e. what I wrote) for k >= 0x40

    mMemInterface->fSelectCardHead = inParams->fCDH;
    mMemInterface->fCylHigh = inParams->fCylHigh;
    mMemInterface->fCylLow = inParams->fCylLow;
    mMemInterface->fSecNum = inParams->fSecNum;
    mMemInterface->fSecCount = inParams->fSecCnt;
    mMemInterface->fError_Feature = inParams->fFeature;
    // I should end with the command register.
    mMemInterface->fStatus_Command = inParams->fCmd;
// The current command is Identify.

    mSocket->SetControl( controls[15] );
// A parameter which works.
// Means kCareAutoIncAddress | kCardPortAccess | kCardByteAccess |
kCardAssembly32;

    if (WaitFor(wait[k & 0x38 >> 3]))
    {
        timeout |= 16;
    }

    if (mMemInterface->fStatus_Command & kStatusReg_ERR)
    {
        theErr = mMemInterface->fError_Feature;
// Well, it failed.
    } else {
        UShort theResult;

          theResult = mMemInterface->fEvenData;
          if (theResult == 0x8A)
          {
           theResult = mMemInterface->fEvenData;
           if (theResult == 0x84)
           {
// The identify command says first 848A (in little endian) as in "I
am a Compact Flash card".

                ULong now = myDelayTimer.GetHardwareTime();
                ULong OKwidth = now - lastOK;
                ULong ResetWidth = now - lastReset;
                lastOK = now;

                if (m == 0)
                {
                 if (timeout & 0x1)
                 {
                  ::printf( "t" );
                 } else {
                  ::printf( "x" );
                 }
                } else {
                 ::printf( "-" );
                }
                if (timeout & 0x2)
                {
                 ::printf( "t" );
                } else {
                 ::printf( "w" );
                }

                if (timeout & 0x10)
                {
                 ::printf( "t " );
                } else {
                 ::printf( "w " );
                }
                ::printf( " %.2X - %.8X, %.8X, %.8X, %.2X\n",
statusWhenWritingCmd, OKwidth, ResetWidth, m, k );

                // Let's empty buffer

                for (i = 0; i < 255; i++)
                {
                 theResult = mMemInterface->fEvenData;
                 theResult |= (mMemInterface->fEvenData << 16);
           }
          }
    } // noErr
  } // m
} // k

mSocket->SetControl( theSavedControl );

::printf( "The End.\n" );
</code>

Here are the logs:

twt means timeout for reset, timeout not reached for first wait,
timeout after second wait.
When I displayed the values of the status register, I discovered it
sometimes was EC, i.e. the command.
That's the same register, but normally, when written it is the
command, and when read, it is the status.
Hence my idea that I haven't configured everything properly.

80 is what is read on the command/status register before I write the command.
First 8 digit hex is the time before the last successful command.
Second hex word is the time before the last reset.
Third word is the index of the command since the last reset. It is
always 0 because I don't succeed in writing two successful
consecutive commands after a reset.

MP120:

twt 80 - 02DF2FB4, 00044208, 00000000, 07
twt 80 - 00CBEEDC, 000441C0, 00000000, 0F
twt 80 - 00CBF0F7, 000441A0, 00000000, 17
twt 80 - 00CAB212, 000491B9, 00000000, 1F
twt 80 - 00CBA3E6, 000441A5, 00000000, 27
twt 80 - 00CCF063, 000441DC, 00000000, 2F
twt 80 - 00CAE1D6, 000441D6, 00000000, 37
twt 80 - 00CC104E, 000441B9, 00000000, 3F
twt 80 - 00CB0C1A, 0004428E, 00000000, 47
twt 80 - 00CC526F, 00044254, 00000000, 4F
twt 80 - 00D4753E, 00048930, 00000000, 57
twt 80 - 00CC33F6, 00044242, 00000000, 5F
twt 80 - 00CB6F47, 0004427B, 00000000, 67
twt 80 - 00CB0408, 0004426D, 00000000, 6F
twt 80 - 00CC1C1A, 00044238, 00000000, 77
twt 80 - 00CAEEB7, 000442BA, 00000000, 7F
The End.

MP 2100:
twt 80 - 17FE6D8A, 0000C0F8, 00000000, 06
twt 80 - 001906D9, 00044149, 00000000, 07
twt 80 - 00AEC625, 0000C0FC, 00000000, 0E
twt 80 - 00190906, 000440FA, 00000000, 0F
twt 80 - 00AF0D43, 0000C0F5, 00000000, 16
twt 80 - 0019340A, 00046376, 00000000, 17
twt 80 - 00AE7AA6, 0000C105, 00000000, 1E
twt 80 - 001906F5, 0004412E, 00000000, 1F
twt 80 - 00AD9F43, 0000C173, 00000000, 26
twt 80 - 00192697, 000440F8, 00000000, 27
twt 80 - 00ADA53E, 0000C11A, 00000000, 2E
twt 80 - 0020B83A, 00044102, 00000000, 2F
twt 80 - 00AC00AA, 0000C0FB, 00000000, 36
twt 80 - 00192D99, 000440F7, 00000000, 37
twt 80 - 00ADAC33, 0000C1A0, 00000000, 3E
twt 80 - 00190F72, 000440FE, 00000000, 3F
twt 80 - 00AE1290, 0000C1CA, 00000000, 46
twt 80 - 001A948F, 00044183, 00000000, 47
twt 80 - 00AC6553, 0000C18A, 00000000, 4E
twt 80 - 001923EC, 00044188, 00000000, 4F
twt 80 - 00AD6A66, 0000C17E, 00000000, 56
twt 80 - 001909F3, 00044190, 00000000, 57
twt 80 - 00AE65F2, 0000C188, 00000000, 5E
twt 80 - 001906A8, 0004418A, 00000000, 5F
twt 80 - 00ADC347, 000157FB, 00000000, 66
twt 80 - 0020A195, 00044234, 00000000, 67
twt 80 - 00ACE354, 0000C18A, 00000000, 6E
twt 80 - 001967CE, 0004418A, 00000000, 6F
twt 80 - 00AE578C, 0000C183, 00000000, 76
twt 80 - 00191C38, 000441D1, 00000000, 77
twt 80 - 00AEAB6E, 0000C18B, 00000000, 7E
twt 80 - 001E3973, 000441CA, 00000000, 7F
The End.

The MP2100 accepts 6 and 7 for the last 3 bits of k, while the MP120
does only accept 7.
This means a wait time of 0x8000 or 0x40000.
All other parameters and wait time gives the same result, and there
is no timeout for the wait after the first setcontrol, which means
that the MP2100 has a real wait time between 0x8000 and 0x4000, and
the MP120 between 0x40000 and 0x8000 (the units are 5th of usec on
MP120 and 4th of usec on MP2100, hence I believe the timeout value is
card dependent, between 6,5 and 8,2 millisecs).

Never I could issue two successive commands.

Any useful information is welcome and would be highly appreciated.

Best regards,

Paul Guyot

-- 
P&M Consulting Newton Program
http://www.pnm-consulting.com/newton/
***************************************
NewtonTalk brought to you by:

EVOTE.COM -- the ESPN of politics on the Internet! All the players, all the news, and the hottest analysis and features (plus 'toons!) anywhere.... visit http://www.evote.com today!

*************************************** Need Subscribe/Unsubscribe info?

Visit the NewtonTalk section at http://www.planetnewton.com



This archive was generated by hypermail 2b29 : Sat Jul 01 2000 - 00:00:06 CDT