      /* format.c -- physically format a disk */

      /* This source is provide by GVP as an example of a program which   */
      /* uses the GVP SCSI device driver to do direct SCSI command I/O    */
      /* to a SCSI device *without using AmigaDOS filesystem, mountlists, */
      /* etc. It is provided for reference only as GVP does not guarantee */
      /* that it functions correctly under all conditions. It will        */
      /* be useful to persons trying to write applications which need     */
      /* to access other (non hard disk) SCSI devices                     */

      /* The necessary INCLUDE file is also included as scsidev.h         */

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

#ifndef EXEC_IO_H
#include <exec/io.h>
#endif

#include <ctype.h>
#include <stdio.h>
#include <functions.h>

#include "scsidev.h"

#define SECOND_COLUMN  40
struct IOStdReq *req;
struct MsgPort *diskport;

   /* Here to resolve references in un-used portions of devface.asm */

int int_server;
int myOpen;
int myClose;
int myExpunge;
int myBeginio;
int myAbortio;
unsigned char   mode_data[12];

unsigned char   test_unit_ready[] =   /* SCSI Test Unit Ready Command   */
{
   0x00,
   0x00,
   0x00,
   0x00,
   0x00,
   0x00
};

unsigned char   start_unit[] =      /* SCSI Start Unit Command   */
{
   0x1B,
   0x00,
   0x00,
   0x00,
   0x01,
   0x00
};

unsigned char   mode_sense[] =      /* SCSI Mode Sense Command   */
{
   0x1A,
   0x00,
   0x3F,
   0x00,
   sizeof(mode_data),
   0x00
};

unsigned char   mode_select[] =      /* SCSI Mode Select Command   */
{
   0x15,
   0x01,
   0x00,
   0x00,
   sizeof(mode_data),
   0x00
};

long unitnumber = 0;
long flags   = 0;
int   lun = 0;         /* Logical Unit Number      */
int   command_length;
unsigned char   data[512];      /* SCSI data         */
unsigned char   linein[80];      /* Input line from console   */

extern char * gets();

main(argc,argv)
int argc;
char *argv[];
{
    ULONG      index;
    unsigned char   done = FALSE;
    unsigned char   server_installed = FALSE;
    int      QUIET,loopct;
    unsigned char   error = FALSE;
    long      dev_open_error = TRUE;
    diskport = CreatePort(0L,0L);
    if (diskport == 0L)
    {
   exit(100);
    }
    req = CreateStdIO(diskport);
    if(argc == 2 && argv[1][0]=='Q')
     {
      QUIET = 1;
     }
    else
     {
      QUIET = 0;
     }
  if (QUIET == 0)
   {
   printf(
     "\nWhat is the AmigaDOS Unit # of the drive you want to format ?\n");
      while (!((unitnumber > 0) && (unitnumber < 9)))
      {
   printf("(1 - 8) ? ");
   gets((char *)linein);
   sscanf(linein,"%ld",&unitnumber);   /* Get response */
      }   
   }
  else
   {
   unitnumber = 1; /* With QUIET option SCSI ID = 0 is always formatted */
   }
    dev_open_error = (long)OpenDevice(MYNAME, unitnumber, req, flags);
    if (dev_open_error)
    {
   printf("\nUnable to open %s.  Run BINDDRIVERS.\n",MYNAME);
    }
    else
    {
      req->io_Command = SD_SCSI;
      req->io_Length = 0L;
      req->io_Data = (APTR)mode_data;
      req->io_Flags = (lun << FLAG_LUN_SHIFT);
      req->io_Offset = (ULONG)start_unit; /* Issue START UNIT command   */
      DoIO(req);

      req->io_Data = (APTR)mode_data;
      req->io_Flags = (lun << FLAG_LUN_SHIFT);
      req->io_Offset = (ULONG)test_unit_ready;
      DoIO(req);      /* Issue TEST UNIT READY command   */
      if (req->io_Error)
      {

       printf("\nUnit NOT READY.  Waiting for ready..");
       while (req->io_Error)
      {
       DoIO(req);
      }
    }
      if (QUIET == 0)
      {
      printf("\nDrive is READY\n");
      }
#ifdef NEEDS_WORK
    req->io_Length = sizeof(mode_data);
    req->io_Offset = (ULONG)mode_sense;      /* Get mode data   */
    DoIO(req);
    if (req->io_Error)
    {
   printf("\nUnable to determine unit's blocksize.\n");
   req->io_Error = 0;         /* Try format anyway   */
    }
    else
    {
   if ((mode_data[9]  != 0) ||      /* If not already 512   */
       (mode_data[10] != 2) ||      /* byte blocksize,   */
       (mode_data[11] != 0))
   {      /* Set it to 512 bytes   */
       mode_data[0]  = 0;
       mode_data[5]  = 0;
       mode_data[6]  = 0;
       mode_data[7]  = 0;
       mode_data[9]  = 0;
       mode_data[10] = 2;
       mode_data[11] = 0;
       req->io_Flags = (lun << FLAG_LUN_SHIFT) | SCSI_SEND;
       req->io_Offset = (ULONG)mode_select;
       DoIO(req);
       if (req->io_Error)
       {
      printf("\nUnable to set blocksize to 512 bytes!\n");
       }
   }
   else
   {
       printf("\nUnit's blocksize is 512 bytes.\n");
   }
      }
#endif
      if (!req->io_Error)
      {         /* Do FORMAT */
  if (QUIET == 0)
  {
   printf(
     "\nProceeding further will destroy any data on your SCSI drive!");
   printf("\nDo you wish to proceed? (Y/N) ");
   while (!gets((char *)linein))   /* Get response */
   {
       printf("\nDo you wish to proceed? (Y/N) ");
   }
  }
  else
  {
   linein[0] = 'y';
  }
   if ('y' == _tolower(linein[0]))
   {
      req->io_Command = SD_FORMAT;
      req->io_Offset = 0L;
      req->io_Length = 512L;
      req->io_Data = (APTR)data;
      req->io_Flags = lun << FLAG_LUN_SHIFT;
      DoIO(req);
      if (req->io_Error)
      {
          printf("\n*****Error in Low-Level (SCSI) Format!\n");
          exit(100);
      }
      else
      {
          printf("\nLow-level (SCSI) Format successful\n");
      }
   }
      }
    }

abort:
    fflush(stdout);

    if (!dev_open_error)
   CloseDevice(req);

    if (!req)
   DeleteStdIO(req);

    if (!diskport)
   DeletePort(diskport);
}
