/*-
 * Copyright (c) 1998 Takanori Watanabe
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	[id for your version control system, if any]
 */
/* 
 * This will get infomation about DIMM from SPD Framework.
 * This must be useless,because it is not OS's busness but BIOS's.
 * This is simply testing smb(4).
 */
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <machine/smb.h>
int fd;
int unit=0;
int smbget(int i)
{
  struct smbcmd cmd;
  unsigned char foo=0;
  bzero(&cmd,sizeof(cmd));
  cmd.slave=0xa0+unit*2;
  cmd.cmd=i;
  cmd.data.byte_ptr=&foo;
  if(ioctl(fd,SMB_READB,&cmd)<0){
    perror("ioctl");  
    exit(-1);
  }
  return foo;
}
main(int argc,char *argv[])
{
  int result;
  fd=open("/dev/smb0",O_RDWR);
  if(fd<0){
    perror("OPEN");
    exit(-1);
  }
  if(argc>1){
    unit=atoi(argv[1]);
    if(unit>8){
      fprintf(stderr,"UNIT EXCEED\n");
      exit(-1);
    }
  }
  printf("DIMM Unit %d\n",unit);
  printf("Bytes used:%d\n",smbget(0));
  printf("Bytes exist:%d\n",1<<smbget(1));
  {
    int i;
    char *type[]={"","EDO","SDRAM",0};
    result=smbget(2);
    printf("Type:");
    for(i=0;type[i]!=0;i++)
      if(result&(1<<i))
	printf("%s",type[i]);
    printf("\n");
  }
  { 
    result=smbget(3);
    printf("Number of ROW bank 1:%d\n",result&0xf);
    printf("Number of ROW bank 2:%d\n",(result>>4)&0xf);
  }
  { 
    result=smbget(4);
    printf("Number of Column bank 1:%d\n",result&0xf);
    printf("Number of Column bank 2:%d\n",(result>>4)&0xf);
  }
  printf("Number of Module row:%d\n",smbget(5));
  printf("Module data width:%d\n",smbget(6)<<8|smbget(7));
  {
    char *type[]={"5.0Vol/TTL","LVTTL","HTSL 1.5","SSTL 3.3","SSTL 2.5"
		    "TBD","TBD",0};
    result=smbget(8);
    if(result<sizeof(type))
      printf("Signal Level:%s\n",type[result]);
  }
  result=smbget(9);
  printf("SDRAM Cycle time %d.%d ns\n",(result>>4)&0xf,result&0xf);
  result=smbget(10);
  printf("SDRAM Access time from Clock %d.%d ns\n",(result>>4)&0xf,result&0xf);
  {
    char *type[]={"None","Parity","ECC",0};
    result=smbget(11);
    printf("Module Configuration Type:%s\n",(result>sizeof(type))?"TBD":type[result]);
  }
  {
    char *type[]={"","/4","/2","*2","*4","*8",0};
    result=smbget(12);
    printf("Refreash Rate:%s 15.625%s us\n",(result&(1<<7))?"Self reflesh":"" 
	   ,((result&127)>sizeof(type))?"TBD":type[result&127]);
  }
  result=smbget(13);
  printf("SDRAM Width:%d %s\n",result&127,
	 (result&128)?"and Bank 2 is 2X width":"");
  result=smbget(14);
  printf("Error Checking SDRAM Width:%d %s\n",result&127,
	 (result&128)?"and Bank 2 is 2X width":"");
  printf("Min Clock Delay:%d\n",smbget(15));
  {
    int i;
    char *type[]={"Length1","Length2","Length4","Length8","TBD"
		    ,"TBD","TBD","Page",0};
    result=smbget(16);
    printf("Burst Length Support:");
    for(i=0;type[i]!=0;i++)
      if(result&(1<<i))
	printf("%s ",type[i]);
    printf("\n");
  }
  printf("Number of Device Banks:%d\n",smbget(17));
  {
    int i;
    result=smbget(18);
    printf("CAS Latacy:");
    for(i=0;i<7;i++)
      if(result&(1<<i))
	printf("%d ",i+1);
    printf("\n");
  }
  {
    int i;
    result=smbget(19);
    printf("CS Latacy:");
    for(i=0;i<7;i++)
      if(result&(1<<i))
	printf("%d ",i);
    printf("\n");
  }
  {
    int i;
    result=smbget(20);
    printf("We Latacy:");
    for(i=0;i<7;i++)
      if(result&(1<<i))
	printf("%d ",i);
    printf("\n");
  }
  {
    int i;
    char *type[]={
      "Buffered addreess control",
      "Registered address control",
      "On Card PLL",
      "Buffered DQMS Input",
      "Registered DQMS Input",
      "Differensial Clock",
      "Redundant Row Addr",
      "TBD"};
		      
    result=smbget(21);
    printf("Module Attribute:");
    for(i=0;type[i]!=0;i++)
      if(result&(1<<i))
	printf("%s, ",type[i]);
    printf("\n");
  }
  {
    int i;
    char *type[]={
      "Early RAS Precharge",
      "Auto RAS Precharge",
      "On Card PLL",
      "Burst R/W",
      "Lower Vcc %5 Torelance",
      "Upper Vcc %5 Torelance",
      "TBD",
      "TBD"};
		      
    result=smbget(21);
    printf("General Attribute:");
    for(i=0;type[i]!=0;i++)
      if(result&(1<<i))
	printf("%s, ",type[i]);
    printf("\n");
  }
  result=smbget(23);
  printf("SDRAM Cycle time(2nd) %d.%d ns\n",(result>>4)&0xf,result&0xf);
  result=smbget(24);
  printf("SDRAM Access time from Clock(2nd) %d.%d ns\n",(result>>4)&0xf,result&0xf);
  result=smbget(25);
  printf("SDRAM Cycle time(3rd) %d.%d ns\n",(result>>4)&0xf,result&0xf);
  result=smbget(26);
  printf("SDRAM Access time from Clock(3rd) %d.%d ns\n",(result>>4)&0xf,result&0xf);
  printf("Minimum Row Precharge:%d ns\n",smbget(27));
  printf("Row Activate:%d ns\n",smbget(28));
  printf("RAS to CAS Delay:%d ns\n",smbget(29));
  printf("Minimum RAS Pulse width:%d ns\n",smbget(30));
  printf("SPD Revision:%d \n",smbget(62));
  {
    int i;
    printf("Manufacturer's JEDEC ID Code:");
    for(i=64;i<=72;i++){
      printf("%x",smbget(i));
    }
    printf("\n");
  }
  printf("Manifacture's Location:%d \n",smbget(72));
  {
    int i;
    printf("Manufacturer's Part no:");
    for(i=73;i<=90;i++){
      printf("%c",smbget(i));
    }
    printf("\n");
  }
  {
    int i;
    printf("Revision no:");
    for(i=91;i<=92;i++){
      printf("%x",smbget(i));
    }
    printf("\n");
  }
  {
    int i;
    printf("Assembly no:");
    for(i=95;i<=98;i++){
      printf("%x",smbget(i));
    }
    printf("\n");
  }
  {
    int i;
    printf("Manufacturer Specific:");
    for(i=99;i<=125;i++){
      printf("%x",smbget(i));
    }
    printf("\n");
  }
  result=smbget(126);
  printf("Freq %s\n",(result==100)?"100":(result==0x66)?"66":"??");
}

