#include <stdio.h>

#include <stdlib.h>
#include <unistd.h>
#include <values.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <fcntl.h>

#include <string.h>
#include <sys/scsi/impl/types.h>
#include <sys/scsi/impl/uscsi.h>
#include <sys/scsi/generic/commands.h>

#define HEX 16
#define GROUP0_PAGESIZE 255
#define GROUP0_CMDSIZE 10
#define GROUP0_RQSIZE 20
#define GROUP0_MODE_SENSE 0x1a
#define LOG_SENSE_CMD                   0x4d
#define GROUP0_MODE_SELECT 0x15

static void output(fp, array, len, num_line)
FILE *fp;
u_char *array;
int len, num_line;
{
        int i;
#if 0
        for(i=0;i<len;i++){
                (void)fprintf(fp, "%2.2x%s", (u_int)array[i],
                        (i+1-num_line)%num_line?" ":"\n");
        }
        if(i%num_line) (void)fprintf (fp, "\n");
#else
	int j;
	for (j=0;j<(len/num_line);j++){
	  for (i=0; i<num_line; i++) {
	    fprintf(fp, "%2.2x ", array[i+j*num_line]);
	  }
	  for (i=0; i<num_line; i++) {
	    fprintf(fp, "%c",
	      isprint(array[i+j*num_line])?array[i+j*num_line]:'.');
	  }
	  fprintf(fp,"\n");
	}
#endif
}

int main() {
  int fd, p;
  struct uscsi_cmd ucmd;
  struct scsi_inquiry inq;
  struct scsi_inquiry *pinq;
  union scsi_cdb cdb;
  u_char rq[GROUP0_RQSIZE];
  unsigned char pagebuf[GROUP0_PAGESIZE];
  unsigned char bigbuf[512];
  int status;

  pinq = (struct scsi_inquiry*)pagebuf;

  fd = open("/dev/rdsk/c0t1d0s2", O_RDONLY|O_NONBLOCK);
  if (fd < 0) {
    perror("open");
    exit(1);
  }

  memset((char *)&ucmd, 0, sizeof(ucmd));
  memset((char *)&cdb, 0, sizeof(union scsi_cdb));
  memset((char *)&pagebuf, 0, sizeof(pagebuf));

  cdb.scc_cmd = SCMD_INQUIRY;
  ucmd.uscsi_cdb = (caddr_t) &cdb;
  ucmd.uscsi_cdblen = CDB_GROUP0;
  FORMG0COUNT(&cdb, ((unsigned)GROUP0_PAGESIZE));
  ucmd.uscsi_bufaddr = (caddr_t)pinq;
  ucmd.uscsi_buflen = GROUP0_PAGESIZE;
  ucmd.uscsi_flags |= USCSI_ISOLATE|USCSI_SILENT|USCSI_READ;
  
  if (ioctl(fd, USCSICMD, &ucmd) < 0) {
    perror("uscsi inq");
  }

  printf("Inquiry done. vendor: <%s>, pid: <%d>, rev: <%d>, serial: <%d>\n",
	 pinq->inq_vid, pinq->inq_pid, pinq->inq_revision, pinq->inq_serial);

#if 0
  for (p=0; p<sizeof(pagebuf); p++) {
    printf("%c", ((char*)&pagebuf)[p]);
  }
#endif

  printf("uscsi_status status: 0x%0x\n\n", ucmd.uscsi_status);

  memset((char *)&ucmd, 0, sizeof(ucmd));
  memset((char *)&cdb, 0, sizeof(union scsi_cdb));
  memset((char *)&pagebuf, 0, sizeof(pagebuf));
  memset(bigbuf, 0, sizeof(bigbuf));

  cdb.scc_cmd = SCMD_READ;
  FORMG0ADDR(&cdb, 321340);
  FORMG0COUNT(&cdb, 1);
  ucmd.uscsi_cdb = (caddr_t) &cdb;
  ucmd.uscsi_cdblen = CDB_GROUP0;
  ucmd.uscsi_bufaddr = (caddr_t)&bigbuf;
  ucmd.uscsi_buflen = sizeof(bigbuf);
  ucmd.uscsi_flags |= USCSI_ISOLATE|USCSI_READ;

  ucmd.uscsi_rqbuf = (caddr_t)rq;
  ucmd.uscsi_rqlen = sizeof(rq);
  ucmd.uscsi_flags |= USCSI_RQENABLE;

  printf("uscsi_status status: 0x%0x\n\n", ucmd.uscsi_status);
  if (ioctl(fd, USCSICMD, &ucmd) < 0) {
    output(stderr, rq, sizeof(rq), 20);
    perror("uscsi read");
    exit(1);
  }


#define OUTPUT_NUM_LINE 12

  output(stdout, (u_char *)bigbuf, sizeof(bigbuf),   OUTPUT_NUM_LINE);

  
#if 0
  printf("\nPage:\t0x%0x\n", pagebuf[0]);
  printf("Len-3:\t%u\n", pagebuf[3]);
  for (p=4; p < pagebuf[3]+4; ) {
    unsigned int v0, v1;
  
    printf("Param %0x, Len %d, Value ",
      (pagebuf[p]<<8) + pagebuf[p+1], pagebuf[p+3]);
  
        v0 = (pagebuf[p+4] << 24) |
             (pagebuf[p+5] << 16) |
             (pagebuf[p+6] <<  8) |
             (pagebuf[p+7]);
  
      if (pagebuf[p+3] == 8) {
        v1 = (pagebuf[p+8] << 24) |
             (pagebuf[p+9] << 16) |
             (pagebuf[p+10] << 8) |
             (pagebuf[p+11]);
        printf("0x%08x.%08x (%d.%d)\n", v0, v1, v0, v1);
      } else if (pagebuf[p+3] == 4) {
        printf("0x%08x (%u)\n", v0, v0);
      } else {
        fprintf(stderr, "funny length %d\n", pagebuf[p+3]);
        exit(1);
      }
    p += 4 + pagebuf[p+3];
  }
#endif  

}
