Netboot Mailing List (by thread)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Intel/DEC 21143 Flash ROM





In message <200002010033.BAA28432@shadow.han.de>, Ken Yap writes:
>
>>I have been searching around for any information on Flash ROM support
>>for a PCI card based on the Intel/DEC 21143 chipset. The board is a
>>TRENDnet TE100-PCIA and has a 28-pin socket on it. I can't find a
>>flashing utility for the TRENDnet card in particular, but maybe
>>someone knows of one for the Intel/DEC 21143 chipset in general?
>
>Flashing tends to be a NIC specific thing rather than a chipset specific
>thing. Chipsets have support for addressing *ROMs but not the extra
>circuitry for programming Flash.
>
>You could try flashing the ROM in a programmer or on another NIC, but
>that makes it harder to upgrade in situ.


here is some code that i wrote for flashing roms on a 21143 nic card.
the rom interface on the 21143 is well defined, so this should work
with most 21143 nics.  it think it possible that some low budget cards
are missing a small latch glue chip needed to allow writes.  in any 
case, hope this helps.  at the bottom is a snippet of code that called
this stuff.  


david.




/*********************************************************************/
/* BootROM programming code.  Specific to Am29F010 flash ROM         */
/*********************************************************************/

/* read a byte from the bootrom.  This can also be done */
/* directly with rombase[offset].  */

unsigned char bootrom_read(unsigned long loc) {
        unsigned long tmp;
        outl(ioaddr + CSR10, loc);  
        outl(ioaddr + CSR9, 0x00005000);  
        udelay(1);
        tmp = inl(ioaddr + CSR9);
        udelay(2);
        return(tmp&0xff);
}

/* cause 21143 to write a byte to the bootrom.  */

void bootrom_write(unsigned long loc, unsigned char val) {
        outl(ioaddr + CSR10, loc);  
        udelay(1);
        outl(ioaddr + CSR9, 0x00003000 | val);
        udelay(2);
}

/* program a byte.  returns 0=success 1=failure */
/* can only change a 1 to a 0.  An erase operation is */
/* necessare to change 0 to a 1.  */  

int bootrom_program_byte(unsigned long offset, unsigned char c) {
  unsigned char val;

  /* write the byte */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0xA0);
  bootrom_write(offset, c);

  /* wait for completion */
  while(1) {  
    val = bootrom_read(offset);  
    if ((val&0x80) == (c&0x80)) return(1);  
    if (val&0x20) {  
      val = bootrom_read(offset);  
      if ((val&0x80) == (c&0x80)) return(1);  
      return(0);  
    }  
  }  
}

/* erase the entire chip.  0=success 1=failure */

int bootrom_erase_chip() {
  unsigned char t1,t2;

  /* erase command */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0x80);
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0x10);

  /* wait for operation to complete*/
  while(1) {
    t1 = bootrom_read(0);
    t2 = bootrom_read(0);
    if ((t1&0x40) == (t2&0x40)) return(1);
    if (t2&0x20) {
      t1 = bootrom_read(0);
      t2 = bootrom_read(0);
      if ((t1&0x40) == (t2&0x40)) return(1);
      bootrom_write(0, 0xF0); /* reset */
      return(0);
    }
  }
}


/* erase a sector of the bootrom.  On the Am29F010 sectors */
/* are 16kB and thus range from 0-7.  Erased sectors become */
/* all 0xFF.  0=success 1=failure  */

int bootrom_sector_erase(unsigned char sector) {
  unsigned long secaddr = sector *  16 * 1024;
  unsigned char t1,t2;

  /* erase sector command */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0x80);
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(secaddr, 0x30);

  /* wait for operation to complete*/
  while(1) {
    t1 = bootrom_read(0);
    t2 = bootrom_read(0);
    if ((t1&0x40) == (t2&0x40)) return(1);
    if (t2&0x20) {
      t1 = bootrom_read(0);
      t2 = bootrom_read(0);
      if ((t1&0x40) == (t2&0x40)) return(1);
      bootrom_write(0, 0xF0); /* reset */
      return(0);
    }
  }
}

/* reset */
/* 5555    AA    2AAA    55    5555    F0 */

void bootrom_reset() {

  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0xF0);

}

/* get Manufacturer ID of the bootrom.  AMD = 0x01 */
/* 5555    AA    2AAA    55    5555    90    XX00    01 */
unsigned char bootrom_get_mfgid() {
  unsigned char mfgid;

  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0x90);

  mfgid = bootrom_read(0);

  /* reset command */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0xF0);

  return(mfgid);
}

/* get the device ID of the bootrom.  AMD Am29F010  == 0x20 */

unsigned char bootrom_get_devid() {
  unsigned char devid;

  /* autoselect command */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0x90);

  devid = bootrom_read(1);

  /* reset command */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0xF0);
 
  return(devid);
}

/* returns a 8bit value telling whether each one of */
/* the eight sectors has write protection turned on */

unsigned char bootrom_get_sec_prot() {
  int sec;
  unsigned char prot = 0;

  /* autoselect command */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0x90);

  /* read protection for each sector */
  for(sec=0;sec<8;sec++) prot |= bootrom_read((sec *  16 * 1024) + 2) << sec;

  /* reset command */
  bootrom_write(0x5555, 0xAA);
  bootrom_write(0x2AAA, 0x55);
  bootrom_write(0x5555, 0xF0);
  
  return(prot);
}




/*************************************************/





int flash_write(char *server, 
                char *mount, 
                char *filename,
                unsigned long location,
                unsigned long size) {

  int fd,rc,x;
  int filesize;
  unsigned char *buf;

  if (location > FLASH_SIZE) {
    printf("flash_write: program location out of range\n");
    return(-1);
  }
  
  fd = nfs_open(server,mount,filename,0);
  if (fd<0) {
    printf("flash_write: nfs_open failed: %s\n",errstr);
    return(-1);
  }

  /* determine length of file */ 
  filesize = nfs_lseek(fd,0,SEEK_END);
  nfs_lseek(fd,0,SEEK_SET); 

  /* take the smaller of size and filesize */
  size = filesize < size? filesize: size;
  
  if (location + size > FLASH_SIZE) {
    printf("flash_write: file too large\n");
    return(-1);
  } 

  buf = malloc(size);
  if (!buf) {
    printf("flash_write: out of memory\n");
    return(-1);
  }

  rc = nfs_read(fd,buf,size);
  if (rc != size) {
    printf("flash_write: error reading %s: %s\n",filename,errstr);
    return(-1);
  } 

  printf("erasing sector:");
  {
     unsigned long fs = location >> 14;
     unsigned long fe = (location+size-1) >> 14;
     if (fs > 7 || fe > 7) {
       printf("flash_write: Flash position or file too large.\n");
       return(0);
     }
     for(x=fs;x<=fe;x++) {
       rc = bootrom_sector_erase(x);
       if (rc) printf(" %d",x);
       else { printf("\n sector %d erase failed.\n",x); return(0); }
     }
  }
  printf(" done.\n");
 
  printf("programming %d bytes at 0x%X ... ",size,location);
  for(x=0;x<size && rc;x++) rc = bootrom_program_byte(x+location,buf[x]);
  if (!rc) { printf("write failed at 0x%X.\n",x); return(0); }
  for(x=0;x<size && rc;x++)
    if (bootrom_read(x+location) != buf[x])  {
      printf("verify failed.\n"); return(0);
    }
  printf("done.\n");

  free(buf);

}











===========================================================================
This Mail was sent to netboot mailing list by:
David Sharp <djs@secure.net>
To get help about this list, send a mail with 'help' as the only string in
it's body to majordomo@baghira.han.de. If you have problems with this list,
send a mail to netboot-owner@baghira.han.de.



For requests or suggestions regarding this mailing list archive please write to netboot@gkminix.han.de.