gdth_proc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:52k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* gdth_proc.c 
  2.  * $Id: gdth_proc.c,v 1.33 2001/08/10 07:54:39 achim Exp $
  3.  */
  4. #include "gdth_ioctl.h"
  5. #if LINUX_VERSION_CODE >= 0x020407
  6. #include <linux/completion.h>
  7. #endif
  8. int gdth_proc_info(char *buffer,char **start,off_t offset,int length,   
  9.                    int hostno,int inout)
  10. {
  11.     int hanum,busnum,i;
  12.     TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %dn",
  13.             length,hostno,(int)offset,inout));
  14.     for (i=0; i<gdth_ctr_vcount; ++i) {
  15.         if (gdth_ctr_vtab[i]->host_no == hostno)
  16.             break;
  17.     }
  18.     if (i==gdth_ctr_vcount)
  19.         return(-EINVAL);
  20.     hanum = NUMDATA(gdth_ctr_vtab[i])->hanum;
  21.     busnum= NUMDATA(gdth_ctr_vtab[i])->busnum;
  22.     if (inout)
  23.         return(gdth_set_info(buffer,length,i,hanum,busnum));
  24.     else
  25.         return(gdth_get_info(buffer,start,offset,length,i,hanum,busnum));
  26. }
  27. static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
  28. {
  29.     int             ret_val;
  30. #if LINUX_VERSION_CODE >= 0x020322
  31.     Scsi_Cmnd       *scp;
  32.     Scsi_Device     *sdev;
  33. #else
  34.     Scsi_Cmnd       scp;
  35.     Scsi_Device     sdev;
  36. #endif
  37.     gdth_iowr_str   *piowr;
  38.     TRACE2(("gdth_set_info() ha %d bus %dn",hanum,busnum));
  39.     piowr = (gdth_iowr_str *)buffer;
  40. #if LINUX_VERSION_CODE >= 0x020322
  41.     sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
  42.     scp  = scsi_allocate_device(sdev, 1, FALSE);
  43.     if (!scp)
  44.         return -ENOMEM;
  45.     scp->cmd_len = 12;
  46.     scp->use_sg = 0;
  47. #else
  48.     memset(&sdev,0,sizeof(Scsi_Device));
  49.     memset(&scp, 0,sizeof(Scsi_Cmnd));
  50.     sdev.host = scp.host = gdth_ctr_vtab[vh];
  51.     sdev.id = scp.target = sdev.host->this_id;
  52.     scp.device = &sdev;
  53. #endif
  54.     if (length >= 4) {
  55.         if (strncmp(buffer,"gdth",4) == 0) {
  56.             buffer += 5;
  57.             length -= 5;
  58.             ret_val = gdth_set_asc_info( buffer, length, hanum, scp );
  59.         } else if (piowr->magic == GDTIOCTL_MAGIC) {
  60.             ret_val = gdth_set_bin_info( buffer, length, hanum, scp );
  61.         } else {
  62.             printk("GDT: Wrong signature %x (%x required)!n",
  63.                    piowr->magic, GDTIOCTL_MAGIC);
  64.             if (piowr->magic > GDTIOCTL_MAGIC)
  65.                 printk("GDT: Please update your driver.n");
  66.             else
  67.                 printk("GDT: Please update your tool.n");
  68.             ret_val = -EINVAL;
  69.         }
  70.     } else {
  71.         ret_val = -EINVAL;
  72.     }
  73. #if LINUX_VERSION_CODE >= 0x020322
  74.     scsi_release_command(scp);
  75.     scsi_free_host_dev(sdev);
  76. #endif
  77.     return ret_val;
  78. }
  79.          
  80. #if LINUX_VERSION_CODE >= 0x020322
  81. static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
  82. #else
  83. static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
  84. #endif
  85. {
  86.     int             orig_length, drive, wb_mode;
  87.     int             i, found;
  88.     gdth_ha_str     *ha;
  89.     gdth_cmd_str    gdtcmd;
  90.     gdth_cpar_str   *pcpar;
  91.     char            cmnd[MAX_COMMAND_SIZE];
  92.     memset(cmnd, 0xff, 12);
  93.     memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
  94.     TRACE2(("gdth_set_asc_info() ha %dn",hanum));
  95.     ha = HADATA(gdth_ctr_tab[hanum]);
  96.     orig_length = length + 5;
  97.     drive = -1;
  98.     wb_mode = 0;
  99.     found = FALSE;
  100.     if (length >= 5 && strncmp(buffer,"flush",5)==0) {
  101.         buffer += 6;
  102.         length -= 6;
  103.         if (length && *buffer>='0' && *buffer<='9') {
  104.             drive = (int)(*buffer-'0');
  105.             ++buffer; --length;
  106.             if (length && *buffer>='0' && *buffer<='9') {
  107.                 drive = drive*10 + (int)(*buffer-'0');
  108.                 ++buffer; --length;
  109.             }
  110.             printk("GDT: Flushing host drive %d .. ",drive);
  111.         } else {
  112.             printk("GDT: Flushing all host drives .. ");
  113.         }
  114.         for (i = 0; i < MAX_HDRIVES; ++i) {
  115.             if (ha->hdr[i].present) {
  116.                 if (drive != -1 && i != drive)
  117.                     continue;
  118.                 found = TRUE;
  119.                 gdtcmd.Service = CACHESERVICE;
  120.                 gdtcmd.OpCode = GDT_FLUSH;
  121.                 gdtcmd.u.cache.DeviceNo = i;
  122.                 gdtcmd.u.cache.BlockNo = 1;
  123. #if LINUX_VERSION_CODE >= 0x020322
  124.                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  125. #else
  126.                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  127. #endif
  128.             }
  129.         }
  130.         if (!found)
  131.             printk("nNo host drive found !n");
  132.         else
  133.             printk("Done.n");
  134.         return(orig_length);
  135.     }
  136.     if (length >= 7 && strncmp(buffer,"wbp_off",7)==0) {
  137.         buffer += 8;
  138.         length -= 8;
  139.         printk("GDT: Disabling write back permanently .. ");
  140.         wb_mode = 1;
  141.     } else if (length >= 6 && strncmp(buffer,"wbp_on",6)==0) {
  142.         buffer += 7;
  143.         length -= 7;
  144.         printk("GDT: Enabling write back permanently .. ");
  145.         wb_mode = 2;
  146.     } else if (length >= 6 && strncmp(buffer,"wb_off",6)==0) {
  147.         buffer += 7;
  148.         length -= 7;
  149.         printk("GDT: Disabling write back commands .. ");
  150.         if (ha->cache_feat & GDT_WR_THROUGH) {
  151.             gdth_write_through = TRUE;
  152.             printk("Done.n");
  153.         } else {
  154.             printk("Not supported !n");
  155.         }
  156.         return(orig_length);
  157.     } else if (length >= 5 && strncmp(buffer,"wb_on",5)==0) {
  158.         buffer += 6;
  159.         length -= 6;
  160.         printk("GDT: Enabling write back commands .. ");
  161.         gdth_write_through = FALSE;
  162.         printk("Done.n");
  163.         return(orig_length);
  164.     }
  165.     if (wb_mode) {
  166.         if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE))
  167.             return(-EBUSY);
  168.         pcpar = (gdth_cpar_str *)ha->pscratch;
  169.         memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
  170.         gdtcmd.Service = CACHESERVICE;
  171.         gdtcmd.OpCode = GDT_IOCTL;
  172.         gdtcmd.u.ioctl.p_param = virt_to_bus(pcpar);
  173.         gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str);
  174.         gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
  175.         gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
  176.         pcpar->write_back = wb_mode==1 ? 0:1;
  177. #if LINUX_VERSION_CODE >= 0x020322
  178.         gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  179. #else
  180.         gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  181. #endif
  182.         gdth_ioctl_free(hanum, ha->pscratch);
  183.         printk("Done.n");
  184.         return(orig_length);
  185.     }
  186.     printk("GDT: Unknown command: %s  Length: %dn",buffer,length);
  187.     return(-EINVAL);
  188. }
  189. #if LINUX_VERSION_CODE >= 0x020322
  190. static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
  191. #else
  192. static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
  193. #endif
  194. {
  195.     unchar          i, j;
  196.     ushort          k, hdr_cnt, status;
  197.     gdth_ha_str     *ha;
  198.     gdth_iowr_str   *piowr;
  199.     gdth_iord_str   *piord;
  200.     gdth_cmd_str    *pcmd;
  201.     gdth_evt_str    *pevt;
  202.     ulong32         *ppadd, add_size, *ppadd2, add_size2, info;
  203.     ulong           flags;
  204.     gdth_cmd_str    gdtcmd;
  205.     int             drv_cyls, drv_hds, drv_secs;
  206.  
  207.     char            cmnd[MAX_COMMAND_SIZE];   
  208.     memset(cmnd, 0xff, 12);
  209.     memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
  210.     TRACE2(("gdth_set_bin_info() ha %dn",hanum));
  211.     ha = HADATA(gdth_ctr_tab[hanum]);
  212.     piowr = (gdth_iowr_str *)buffer;
  213.     piord = NULL;
  214.     pcmd = NULL;
  215.     ppadd = ppadd2 = NULL;
  216.     add_size = add_size2 = 0;
  217.     if (length < GDTOFFSOF(gdth_iowr_str,iu))
  218.         return(-EINVAL);
  219.     switch (piowr->ioctl) {
  220.       case GDTIOCTL_GENERAL:
  221.         if (length < GDTOFFSOF(gdth_iowr_str,iu.general.data[0]))
  222.             return(-EINVAL);
  223.         pcmd = (gdth_cmd_str *)piowr->iu.general.command;
  224.         pcmd->Service = piowr->service;
  225.         if (pcmd->OpCode == GDT_IOCTL) {
  226.             ppadd = &pcmd->u.ioctl.p_param;
  227.             add_size = pcmd->u.ioctl.param_size;
  228.         } else if (piowr->service == CACHESERVICE) {
  229.             add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE;
  230.             if (ha->cache_feat & SCATTER_GATHER) {
  231.                 ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr;
  232.                 pcmd->u.cache.DestAddr = 0xffffffff;
  233.                 pcmd->u.cache.sg_lst[0].sg_len = add_size;
  234.                 pcmd->u.cache.sg_canz = 1;
  235.             } else {
  236.                 ppadd = &pcmd->u.cache.DestAddr;
  237.                 pcmd->u.cache.sg_canz = 0;
  238.             }
  239.         } else if (piowr->service == SCSIRAWSERVICE) {
  240.             add_size = pcmd->u.raw.sdlen;
  241.             add_size2 = pcmd->u.raw.sense_len;
  242.             if (ha->raw_feat & SCATTER_GATHER) {
  243.                 ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr;
  244.                 pcmd->u.raw.sdata = 0xffffffff;
  245.                 pcmd->u.raw.sg_lst[0].sg_len = add_size;
  246.                 pcmd->u.raw.sg_ranz = 1;
  247.             } else {
  248.                 ppadd = &pcmd->u.raw.sdata;
  249.                 pcmd->u.raw.sg_ranz = 0;
  250.             }
  251.             ppadd2 = &pcmd->u.raw.sense_data;
  252.         } else {
  253.             return(-EINVAL);
  254.         }
  255.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2,
  256.                                TRUE ))
  257.             return(-EBUSY);
  258.         piord = (gdth_iord_str *)ha->pscratch;
  259.         piord->size = sizeof(gdth_iord_str) + add_size + add_size2;
  260.         if (add_size > 0) {
  261.             memcpy(piord->iu.general.data, piowr->iu.general.data, add_size);
  262.             *ppadd = virt_to_bus(piord->iu.general.data);
  263.         }
  264.         if (add_size2 > 0) {
  265.             memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2);
  266.             *ppadd2 = virt_to_bus(piord->iu.general.data+add_size);
  267.         }
  268.         /* do IOCTL */
  269. #if LINUX_VERSION_CODE >= 0x020322
  270.         gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
  271.         piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
  272. #else
  273.         gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
  274.         piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
  275. #endif
  276.         break;
  277.       case GDTIOCTL_DRVERS:
  278.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  279.             return(-EBUSY);
  280.         piord = (gdth_iord_str *)ha->pscratch;
  281.         piord->size = sizeof(gdth_iord_str);
  282.         piord->status = S_OK;
  283.         piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
  284.         break;
  285.       case GDTIOCTL_CTRTYPE:
  286.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  287.             return(-EBUSY);
  288.         piord = (gdth_iord_str *)ha->pscratch;
  289.         piord->size = sizeof(gdth_iord_str);
  290.         piord->status = S_OK;
  291.         if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
  292.             piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10);
  293.         } else {
  294.             if (ha->type != GDT_PCIMPR) {
  295.                 piord->iu.ctrtype.type = (unchar)((ha->stype<<4) + 6);
  296.             } else {
  297.                 piord->iu.ctrtype.type = 
  298.                     (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
  299.                 if (ha->stype >= 0x300)
  300.                     piord->iu.ctrtype.ext_type = 0x6000 | ha->subdevice_id;
  301.                 else 
  302.                     piord->iu.ctrtype.ext_type = 0x6000 | ha->stype;
  303.             }
  304.             piord->iu.ctrtype.device_id = ha->stype;
  305.             piord->iu.ctrtype.sub_device_id = ha->subdevice_id;
  306.         }
  307.         piord->iu.ctrtype.info = ha->brd_phys;
  308.         piord->iu.ctrtype.oem_id = ha->oem_id;
  309.         break;
  310.       case GDTIOCTL_CTRCNT:
  311.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  312.             return(-EBUSY);
  313.         piord = (gdth_iord_str *)ha->pscratch;
  314.         piord->size = sizeof(gdth_iord_str);
  315.         piord->status = S_OK;
  316.         piord->iu.ctrcnt.count = (ushort)gdth_ctr_count;
  317.         break;
  318.       case GDTIOCTL_OSVERS:
  319.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  320.             return(-EBUSY);
  321.         piord = (gdth_iord_str *)ha->pscratch;
  322.         piord->size = sizeof(gdth_iord_str);
  323.         piord->status = S_OK;
  324.         piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16);
  325.         piord->iu.osvers.subversion = (unchar)(LINUX_VERSION_CODE >> 8);
  326.         piord->iu.osvers.revision = (ushort)(LINUX_VERSION_CODE & 0xff);
  327.         break;
  328.       case GDTIOCTL_LOCKDRV:
  329.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  330.             return(-EBUSY);
  331.         piord = (gdth_iord_str *)ha->pscratch;
  332.         for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
  333.             j = piowr->iu.lockdrv.drives[i];
  334.             if (j >= MAX_HDRIVES || !ha->hdr[j].present) 
  335.                 continue;
  336.             if (piowr->iu.lockdrv.lock) {
  337.                 GDTH_LOCK_HA(ha, flags);
  338.                 ha->hdr[j].lock = 1;
  339.                 GDTH_UNLOCK_HA(ha, flags);
  340.                 gdth_wait_completion( hanum, ha->bus_cnt, j );
  341.                 gdth_stop_timeout( hanum, ha->bus_cnt, j );
  342.             } else {
  343.                 GDTH_LOCK_HA(ha, flags);
  344.                 ha->hdr[j].lock = 0;
  345.                 GDTH_UNLOCK_HA(ha, flags);
  346.                 gdth_start_timeout( hanum, ha->bus_cnt, j );
  347.                 gdth_next( hanum );
  348.             }
  349.         }
  350.         piord->size = sizeof(gdth_iord_str);
  351.         piord->status = S_OK;
  352.         break;
  353.       case GDTIOCTL_LOCKCHN:
  354.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  355.             return(-EBUSY);
  356.         i = piowr->iu.lockchn.channel;
  357.         if (i < ha->bus_cnt) {
  358.             if (piowr->iu.lockchn.lock) {
  359.                 GDTH_LOCK_HA(ha, flags);
  360.                 ha->raw[i].lock = 1;
  361.                 GDTH_UNLOCK_HA(ha, flags);
  362.                 for (j = 0; j < ha->tid_cnt; ++j) {
  363.                     gdth_wait_completion( hanum, i, j );
  364.                     gdth_stop_timeout( hanum, i, j );
  365.                 }
  366.             } else {
  367.                 GDTH_LOCK_HA(ha, flags);
  368.                 ha->raw[i].lock = 0;
  369.                 GDTH_UNLOCK_HA(ha, flags);
  370.                 for (j = 0; j < ha->tid_cnt; ++j) {
  371.                     gdth_start_timeout( hanum, i, j );
  372.                     gdth_next( hanum );
  373.                 }
  374.             }
  375.         }
  376.         piord = (gdth_iord_str *)ha->pscratch;
  377.         piord->size = sizeof(gdth_iord_str);
  378.         piord->status = S_OK;
  379.         break;
  380.       case GDTIOCTL_EVENT:
  381.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  382.             return(-EBUSY);
  383.         piord = (gdth_iord_str *)ha->pscratch;
  384.         if (piowr->iu.event.erase == 0xff) {
  385.             pevt = (gdth_evt_str *)piowr->iu.event.evt;
  386.             if (pevt->event_source == ES_TEST) 
  387.                 pevt->event_data.size = sizeof(pevt->event_data.eu.test);
  388.             else if (pevt->event_source == ES_DRIVER) 
  389.                 pevt->event_data.size = sizeof(pevt->event_data.eu.driver);
  390.             else if (pevt->event_source == ES_SYNC) 
  391.                 pevt->event_data.size = sizeof(pevt->event_data.eu.sync);
  392.             else {
  393.                 pevt->event_data.size = sizeof(pevt->event_data.eu.async);
  394.                 gdth_log_event(&pevt->event_data, NULL);
  395.             }
  396.             GDTH_LOCK_HA(ha, flags);
  397.             gdth_store_event(ha, pevt->event_source, pevt->event_idx,
  398.                              &pevt->event_data);
  399.             GDTH_UNLOCK_HA(ha, flags);
  400.         } else if (piowr->iu.event.erase == 0xfe) {
  401.             gdth_clear_events();
  402.         } else if (piowr->iu.event.erase == 0) {
  403.             piord->iu.event.handle = 
  404.                 gdth_read_event(ha,piowr->iu.event.handle,
  405.                                 (gdth_evt_str *)piord->iu.event.evt);
  406.         } else {
  407.             piord->iu.event.handle = piowr->iu.event.handle;
  408.             gdth_readapp_event(ha, (unchar)piowr->iu.event.erase,
  409.                                (gdth_evt_str *)piord->iu.event.evt);
  410.         }
  411.         piord->size = sizeof(gdth_iord_str);
  412.         piord->status = S_OK;
  413.         break;
  414.       case GDTIOCTL_SCSI:
  415.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  416.             return(-EBUSY);
  417.         piord = (gdth_iord_str *)ha->pscratch;
  418.         piord->size = sizeof(gdth_iord_str);
  419.         memcpy(cmnd, piowr->iu.scsi.cmd, 12);
  420. #if LINUX_VERSION_CODE >= 0x020322
  421.         scp->target = piowr->iu.scsi.target;
  422.         scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
  423.         scp->cmd_len = piowr->iu.scsi.cmd_len;
  424.         gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
  425.         piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
  426. #else
  427.         scp.target = piowr->iu.scsi.target;
  428.         scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
  429.         scp.cmd_len = piowr->iu.scsi.cmd_len;
  430.         gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
  431.         piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
  432. #endif
  433.         break;
  434.       case GDTIOCTL_RESET_BUS:
  435.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  436.             return(-EBUSY);
  437.         piord = (gdth_iord_str *)ha->pscratch;
  438.         piord->size = sizeof(gdth_iord_str);
  439. #if LINUX_VERSION_CODE >= 0x020322
  440.         scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
  441.         piord->status = (ulong32)gdth_eh_bus_reset( scp );
  442.         if (piord->status == SUCCESS)
  443.             piord->status = S_OK;
  444.         else
  445.             piord->status = S_GENERR;
  446. #elif LINUX_VERSION_CODE >= 0x02015F
  447.         scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
  448.         piord->status = (ulong32)gdth_eh_bus_reset( &scp );
  449.         if (piord->status == SUCCESS)
  450.             piord->status = S_OK;
  451.         else
  452.             piord->status = S_GENERR;
  453. #else
  454.         piord->status = S_OK;
  455. #endif
  456.         break;
  457.       case GDTIOCTL_HDRLIST:
  458.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  459.             return(-EBUSY);
  460.         piord = (gdth_iord_str *)ha->pscratch;
  461.         piord->size = sizeof(gdth_iord_str);
  462.         piord->status = S_OK;
  463.         for (i = 0; i < MAX_HDRIVES; ++i) {
  464.             if (ha->hdr[i].present) {
  465.                 piord->iu.hdr_list[i].bus = ha->virt_bus;
  466.                 piord->iu.hdr_list[i].target = i;
  467.                 piord->iu.hdr_list[i].lun = 0;
  468.                 piord->iu.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
  469.                 if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {  
  470.                     gdtcmd.Service = CACHESERVICE;
  471.                     gdtcmd.OpCode = GDT_CLUST_INFO;
  472.                     gdtcmd.u.cache.DeviceNo = i;
  473. #if LINUX_VERSION_CODE >= 0x020322
  474.                     gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  475.                     if (scp->SCp.Status == S_OK)
  476.                         piord->iu.hdr_list[i].cluster_type = 
  477.                             (unchar)scp->SCp.Message;
  478. #else
  479.                     gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  480.                     if (scp.SCp.Status == S_OK)
  481.                         piord->iu.hdr_list[i].cluster_type = 
  482.                             (unchar)scp.SCp.Message;
  483. #endif
  484.                 }
  485.             } else {
  486.                 piord->iu.hdr_list[i].bus = 0xff;
  487.             }
  488.         }
  489.         break;
  490.       case GDTIOCTL_RESCAN:
  491.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  492.             return(-EBUSY);
  493.         piord = (gdth_iord_str *)ha->pscratch;
  494.         piord->size = sizeof(gdth_iord_str);
  495.         piord->status = S_OK;
  496.         if (piowr->iu.rescan.flag == 0) {
  497.             /* old method: scan all host drives 
  498.                re-initialize cache service to get host drive count
  499.             */
  500.             gdtcmd.Service = CACHESERVICE;
  501.             gdtcmd.OpCode = GDT_INIT;
  502.             gdtcmd.u.cache.DeviceNo = LINUX_OS;
  503. #if LINUX_VERSION_CODE >= 0x020322
  504.             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  505.             status = (ushort)scp->SCp.Status; 
  506.             info = (ulong32)scp->SCp.Message;
  507. #else
  508.             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  509.             status = (ushort)scp.SCp.Status;
  510.             info = (ulong32)scp.SCp.Message;
  511. #endif
  512.             if (status != S_OK)
  513.                 break;
  514.             k = 0;
  515.             hdr_cnt = (ushort)info;
  516.         } else {
  517.             k = piowr->iu.rescan.hdr_no;
  518.             hdr_cnt = k + 1;
  519.         }
  520.         if (hdr_cnt > MAX_HDRIVES)
  521.             hdr_cnt = MAX_HDRIVES;
  522.         /* scanning for host drives */
  523.         for (; k < hdr_cnt; ++k) {
  524.             /* info about host drive */
  525.             gdtcmd.Service = CACHESERVICE;
  526.             gdtcmd.OpCode = GDT_INFO;
  527.             gdtcmd.u.cache.DeviceNo = k;
  528. #if LINUX_VERSION_CODE >= 0x020322
  529.             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  530.             status = (ushort)scp->SCp.Status; 
  531.             info = (ulong32)scp->SCp.Message;
  532. #else
  533.             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  534.             status = (ushort)scp.SCp.Status;
  535.             info = (ulong32)scp.SCp.Message;
  536. #endif
  537.             GDTH_LOCK_HA(ha, flags);
  538.             piord->iu.hdr_list[k].bus = ha->virt_bus;
  539.             piord->iu.hdr_list[k].target = k;
  540.             piord->iu.hdr_list[k].lun = 0;
  541.             if (status != S_OK) {
  542.                 ha->hdr[k].present = FALSE;
  543.             } else {
  544.                 ha->hdr[k].present = TRUE;
  545.                 ha->hdr[k].size = info;
  546.                 /* evaluate mapping (sectors per head, heads per cylinder) */
  547.                 ha->hdr[k].size &= ~SECS32;
  548.                 gdth_eval_mapping(ha->hdr[k].size,&drv_cyls,&drv_hds,&drv_secs);
  549.                 ha->hdr[k].heads = (unchar)drv_hds;
  550.                 ha->hdr[k].secs = (unchar)drv_secs;
  551.                 /* round size */
  552.                 ha->hdr[k].size = drv_cyls * drv_hds * drv_secs;
  553.             }
  554.             GDTH_UNLOCK_HA(ha, flags);
  555.             if (status != S_OK)
  556.                 continue;       /* next host drive */
  557.             /* devtype, cluster info, R/W attributes */
  558.             gdtcmd.Service = CACHESERVICE;
  559.             gdtcmd.OpCode = GDT_DEVTYPE;
  560.             gdtcmd.u.cache.DeviceNo = k;
  561. #if LINUX_VERSION_CODE >= 0x020322
  562.             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  563.             status = (ushort)scp->SCp.Status; 
  564.             info = (ulong32)scp->SCp.Message;
  565. #else
  566.             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  567.             status = (ushort)scp.SCp.Status;
  568.             info = (ulong32)scp.SCp.Message;
  569. #endif
  570.             GDTH_LOCK_HA(ha, flags);
  571.             ha->hdr[k].devtype = 0;
  572.             if (status == S_OK)
  573.                 ha->hdr[k].devtype = (ushort)info;
  574.             GDTH_UNLOCK_HA(ha, flags);
  575.             gdtcmd.Service = CACHESERVICE;
  576.             gdtcmd.OpCode = GDT_CLUST_INFO;
  577.             gdtcmd.u.cache.DeviceNo = k;
  578. #if LINUX_VERSION_CODE >= 0x020322
  579.             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  580.             status = (ushort)scp->SCp.Status; 
  581.             info = (ulong32)scp->SCp.Message;
  582. #else
  583.             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  584.             status = (ushort)scp.SCp.Status;
  585.             info = (ulong32)scp.SCp.Message;
  586. #endif
  587.             GDTH_LOCK_HA(ha, flags);
  588.             ha->hdr[k].cluster_type = 0;
  589.             if (status == S_OK && !shared_access)
  590.                 ha->hdr[k].cluster_type = (ushort)info;
  591.             GDTH_UNLOCK_HA(ha, flags);
  592.             piord->iu.hdr_list[k].cluster_type = ha->hdr[k].cluster_type;
  593.             gdtcmd.Service = CACHESERVICE;
  594.             gdtcmd.OpCode = GDT_RW_ATTRIBS;
  595.             gdtcmd.u.cache.DeviceNo = k;
  596. #if LINUX_VERSION_CODE >= 0x020322
  597.             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  598.             status = (ushort)scp->SCp.Status; 
  599.             info = (ulong32)scp->SCp.Message;
  600. #else
  601.             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  602.             status = (ushort)scp.SCp.Status;
  603.             info = (ulong32)scp.SCp.Message;
  604. #endif
  605.             GDTH_LOCK_HA(ha, flags);
  606.             ha->hdr[k].rw_attribs = 0;
  607.             if (status == S_OK)
  608.                 ha->hdr[k].rw_attribs = (ushort)info;
  609.             GDTH_UNLOCK_HA(ha, flags);
  610.         }
  611.         break;
  612.       case GDTIOCTL_RESET_DRV:
  613.         if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
  614.             return(-EBUSY);
  615.         piord = (gdth_iord_str *)ha->pscratch;
  616.         piord->size = sizeof(gdth_iord_str);
  617.         piord->status = S_OK;
  618.         i = piowr->iu.scsi.target;
  619.         if (ha->hdr[i].present) {
  620.             gdtcmd.Service = CACHESERVICE;
  621.             gdtcmd.OpCode = GDT_CLUST_RESET;
  622.             gdtcmd.u.cache.DeviceNo = i;
  623. #if LINUX_VERSION_CODE >= 0x020322
  624.             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  625.             piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
  626. #else
  627.             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  628.             piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
  629. #endif
  630.         }
  631.         break;
  632.       default:
  633.         return(-EINVAL);
  634.     }
  635.     return length;
  636. }
  637. static int gdth_get_info(char *buffer,char **start,off_t offset,
  638.                          int length,int vh,int hanum,int busnum)
  639. {
  640.     int size = 0,len = 0;
  641.     off_t begin = 0,pos = 0;
  642.     gdth_ha_str *ha;
  643.     gdth_iord_str *piord;
  644.     int id, i, j, k, sec, flag;
  645.     int no_mdrv = 0, drv_no, is_mirr;
  646.     ulong32 cnt;
  647.     gdth_cmd_str gdtcmd;
  648.     gdth_evt_str estr;
  649. #if LINUX_VERSION_CODE >= 0x020322
  650.     Scsi_Cmnd *scp;
  651.     Scsi_Device *sdev;
  652. #else
  653.     Scsi_Cmnd scp;
  654.     Scsi_Device sdev;
  655. #endif
  656.     char hrec[161];
  657.     struct timeval tv;
  658.     char *buf;
  659.     gdth_dskstat_str *pds;
  660.     gdth_diskinfo_str *pdi;
  661.     gdth_arrayinf_str *pai;
  662.     gdth_defcnt_str *pdef;
  663.     gdth_cdrinfo_str *pcdi;
  664.     gdth_hget_str *phg;
  665.     char cmnd[MAX_COMMAND_SIZE];
  666.     memset(cmnd, 0xff, 12);
  667.     memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
  668.     TRACE2(("gdth_get_info() ha %d bus %dn",hanum,busnum));
  669.     ha = HADATA(gdth_ctr_tab[hanum]);
  670. #if LINUX_VERSION_CODE >= 0x020322
  671.     sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
  672.     scp  = scsi_allocate_device(sdev, 1, FALSE);
  673.     if (!scp)
  674.         return -ENOMEM;
  675.     scp->cmd_len = 12;
  676.     scp->use_sg = 0;
  677. #else
  678.     memset(&sdev,0,sizeof(Scsi_Device));
  679.     memset(&scp, 0,sizeof(Scsi_Cmnd));
  680.     sdev.host = scp.host = gdth_ctr_vtab[vh];
  681.     sdev.id = scp.target = sdev.host->this_id;
  682.     scp.device = &sdev;
  683. #endif
  684.     /* ioctl from tool? */
  685.     if (!gdth_ioctl_check_bin(hanum, (ushort)length)) {
  686.         /* request is i.e. "cat /proc/scsi/gdth/0" */ 
  687.         /* format: %-15st%-10st%-15st%s */
  688.         /* driver parameters */
  689.         size = sprintf(buffer+len,"Driver Parameters:n");
  690.         len += size;  pos = begin + len;
  691.         if (reserve_list[0] == 0xff)
  692.             strcpy(hrec, "--");
  693.         else {
  694.             sprintf(hrec, "%d", reserve_list[0]);
  695.             for (i = 1;  i < MAX_RES_ARGS; i++) {
  696.                 if (reserve_list[i] == 0xff) 
  697.                     break;
  698.                 sprintf(hrec,"%s,%d", hrec, reserve_list[i]);
  699.             }
  700.         }
  701.         size = sprintf(buffer+len,
  702.                        " reserve_mode: t%d         treserve_list:  t%sn",
  703.                        reserve_mode, hrec);
  704.         len += size;  pos = begin + len;
  705.         size = sprintf(buffer+len,
  706.                        " max_ids:      t%-3d       thdr_channel:   t%dn",
  707.                        max_ids, hdr_channel);
  708.         len += size;  pos = begin + len;
  709.         /* controller information */
  710.         size = sprintf(buffer+len,"nDisk Array Controller Information:n");
  711.         len += size;  pos = begin + len;
  712.         if (virt_ctr)
  713.             sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
  714.         else
  715.             strcpy(hrec, ha->binfo.type_string);
  716.         size = sprintf(buffer+len,
  717.                        " Number:       t%d         tName:          t%sn",
  718.                        hanum, hrec);
  719.         len += size;  pos = begin + len;
  720.         if (ha->more_proc)
  721.             sprintf(hrec, "%d.%02d.%02d-%c%03X", 
  722.                     (unchar)(ha->binfo.upd_fw_ver>>24),
  723.                     (unchar)(ha->binfo.upd_fw_ver>>16),
  724.                     (unchar)(ha->binfo.upd_fw_ver),
  725.                     ha->bfeat.raid ? 'R':'N',
  726.                     ha->binfo.upd_revision);
  727.         else
  728.             sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8),
  729.                     (unchar)(ha->cpar.version));
  730.         size = sprintf(buffer+len,
  731.                        " Driver Ver.:  t%-10stFirmware Ver.: t%sn",
  732.                        GDTH_VERSION_STR, hrec);
  733.         len += size;  pos = begin + len;
  734.  
  735.         if (pos < offset) {
  736.             len = 0;
  737.             begin = pos;
  738.         }
  739.         if (pos > offset + length)
  740.             goto stop_output;
  741.         if (ha->more_proc) {
  742.             /* more information: 1. about controller */
  743.             size = sprintf(buffer+len,
  744.                            " Serial No.:   t0x%8XtCache RAM size:t%d KBn",
  745.                            ha->binfo.ser_no, ha->binfo.memsize / 1024);
  746.             len += size;  pos = begin + len;
  747.             /* 2. about physical devices */
  748.             size = sprintf(buffer+len,"nPhysical Devices:");
  749.             len += size;  pos = begin + len;
  750.             flag = FALSE;
  751.             
  752.             buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
  753.             if (!buf) 
  754.                 goto stop_output;
  755.             for (i = 0; i < ha->bus_cnt; ++i) {
  756.                 /* 2.a statistics (and retries/reassigns) */
  757.                 TRACE2(("pdr_statistics() chn %dn",i));                
  758.                 pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
  759.                 gdtcmd.Service = CACHESERVICE;
  760.                 gdtcmd.OpCode = GDT_IOCTL;
  761.                 gdtcmd.u.ioctl.p_param = virt_to_bus(pds);
  762.                 gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
  763.                 gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
  764.                 gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
  765.                 pds->bid = ha->raw[i].local_no;
  766.                 pds->first = 0;
  767.                 pds->entries = ha->raw[i].pdev_cnt;
  768.                 cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) /
  769.                     sizeof(pds->list[0]);
  770.                 if (pds->entries > cnt)
  771.                     pds->entries = cnt;
  772. #if LINUX_VERSION_CODE >= 0x020322
  773.                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  774.                 if (scp->SCp.Status != S_OK) 
  775. #else
  776.                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  777.                 if (scp.SCp.Status != S_OK) 
  778. #endif
  779.                 { 
  780.                     pds->count = 0;
  781.                 }
  782.                 /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
  783.                 for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
  784.                     /* 2.b drive info */
  785.                     TRACE2(("scsi_drv_info() chn %d dev %dn",
  786.                         i, ha->raw[i].id_list[j]));             
  787.                     pdi = (gdth_diskinfo_str *)buf;
  788.                     gdtcmd.Service = CACHESERVICE;
  789.                     gdtcmd.OpCode = GDT_IOCTL;
  790.                     gdtcmd.u.ioctl.p_param = virt_to_bus(pdi);
  791.                     gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
  792.                     gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
  793.                     gdtcmd.u.ioctl.channel = 
  794.                         ha->raw[i].address | ha->raw[i].id_list[j];
  795. #if LINUX_VERSION_CODE >= 0x020322
  796.                     gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  797.                     if (scp->SCp.Status == S_OK) 
  798. #else
  799.                     gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  800.                     if (scp.SCp.Status == S_OK) 
  801. #endif
  802.                     {
  803.                         strncpy(hrec,pdi->vendor,8);
  804.                         strncpy(hrec+8,pdi->product,16);
  805.                         strncpy(hrec+24,pdi->revision,4);
  806.                         hrec[28] = 0;
  807.                         size = sprintf(buffer+len,
  808.                                        "n Chn/ID/LUN:   t%c/%02d/%d    tName:          t%sn",
  809.                                        'A'+i,pdi->target_id,pdi->lun,hrec);
  810.                         len += size;  pos = begin + len;
  811.                         flag = TRUE;
  812.                         pdi->no_ldrive &= 0xffff;
  813.                         if (pdi->no_ldrive == 0xffff)
  814.                             strcpy(hrec,"--");
  815.                         else
  816.                             sprintf(hrec,"%d",pdi->no_ldrive);
  817.                         size = sprintf(buffer+len,
  818.                                        " Capacity [MB]:t%-6d    tTo Log. Drive: t%sn",
  819.                                        pdi->blkcnt/(1024*1024/pdi->blksize),
  820.                                        hrec);
  821.                         len += size;  pos = begin + len;
  822.                     } else {
  823.                         pdi->devtype = 0xff;
  824.                     }
  825.                     
  826.                     if (pdi->devtype == 0) {
  827.                         /* search retries/reassigns */
  828.                         for (k = 0; k < pds->count; ++k) {
  829.                             if (pds->list[k].tid == pdi->target_id &&
  830.                                 pds->list[k].lun == pdi->lun) {
  831.                                 size = sprintf(buffer+len,
  832.                                                " Retries:      t%-6d    tReassigns:     t%dn",
  833.                                                pds->list[k].retries,
  834.                                                pds->list[k].reassigns);
  835.                                 len += size;  pos = begin + len;
  836.                                 break;
  837.                             }
  838.                         }
  839.                         /* 2.c grown defects */
  840.                         TRACE2(("scsi_drv_defcnt() chn %d dev %dn",
  841.                                 i, ha->raw[i].id_list[j]));             
  842.                         pdef = (gdth_defcnt_str *)buf;
  843.                         gdtcmd.Service = CACHESERVICE;
  844.                         gdtcmd.OpCode = GDT_IOCTL;
  845.                         gdtcmd.u.ioctl.p_param = virt_to_bus(pdef);
  846.                         gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
  847.                         gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
  848.                         gdtcmd.u.ioctl.channel = 
  849.                             ha->raw[i].address | ha->raw[i].id_list[j];
  850.                         pdef->sddc_type = 0x08;
  851. #if LINUX_VERSION_CODE >= 0x020322
  852.                         gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  853.                         if (scp->SCp.Status == S_OK) 
  854. #else
  855.                         gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  856.                         if (scp.SCp.Status == S_OK) 
  857. #endif
  858.                         {
  859.                             size = sprintf(buffer+len,
  860.                                            " Grown Defects:t%dn",
  861.                                            pdef->sddc_cnt);
  862.                             len += size;  pos = begin + len;
  863.                         }
  864.                     }
  865.                     if (pos < offset) {
  866.                         len = 0;
  867.                         begin = pos;
  868.                     }
  869.                     if (pos > offset + length)
  870.                         goto stop_output;
  871.                 }
  872.             }
  873.             gdth_ioctl_free(hanum, buf);
  874.             if (!flag) {
  875.                 size = sprintf(buffer+len, "n --n");
  876.                 len += size;  pos = begin + len;
  877.             }
  878.             /* 3. about logical drives */
  879.             size = sprintf(buffer+len,"nLogical Drives:");
  880.             len += size;  pos = begin + len;
  881.             flag = FALSE;
  882.             buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
  883.             if (!buf) 
  884.                 goto stop_output;
  885.             for (i = 0; i < MAX_LDRIVES; ++i) {
  886.                 if (!ha->hdr[i].is_logdrv)
  887.                     continue;
  888.                 drv_no = i;
  889.                 j = k = 0;
  890.                 is_mirr = FALSE;
  891.                 do {
  892.                     /* 3.a log. drive info */
  893.                     TRACE2(("cache_drv_info() drive no %dn",drv_no));
  894.                     pcdi = (gdth_cdrinfo_str *)buf;
  895.                     gdtcmd.Service = CACHESERVICE;
  896.                     gdtcmd.OpCode = GDT_IOCTL;
  897.                     gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi);
  898.                     gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
  899.                     gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
  900.                     gdtcmd.u.ioctl.channel = drv_no;
  901. #if LINUX_VERSION_CODE >= 0x020322
  902.                     gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  903.                     if (scp->SCp.Status != S_OK)
  904. #else
  905.                     gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  906.                     if (scp.SCp.Status != S_OK)
  907. #endif
  908.                     {
  909.                         break;
  910.                     }
  911.                     pcdi->ld_dtype >>= 16;
  912.                     j++;
  913.                     if (pcdi->ld_dtype > 2) {
  914.                         strcpy(hrec, "missing");
  915.                     } else if (pcdi->ld_error & 1) {
  916.                         strcpy(hrec, "fault");
  917.                     } else if (pcdi->ld_error & 2) {
  918.                         strcpy(hrec, "invalid");
  919.                         k++; j--;
  920.                     } else {
  921.                         strcpy(hrec, "ok");
  922.                     }
  923.                     
  924.                     if (drv_no == i) {
  925.                         size = sprintf(buffer+len,
  926.                                        "n Number:       t%-2d        tStatus:        t%sn",
  927.                                        drv_no, hrec);
  928.                         len += size;  pos = begin + len;
  929.                         flag = TRUE;
  930.                         no_mdrv = pcdi->cd_ldcnt;
  931.                         if (no_mdrv > 1 || pcdi->ld_slave != -1) {
  932.                             is_mirr = TRUE;
  933.                             strcpy(hrec, "RAID-1");
  934.                         } else if (pcdi->ld_dtype == 0) {
  935.                             strcpy(hrec, "Disk");
  936.                         } else if (pcdi->ld_dtype == 1) {
  937.                             strcpy(hrec, "RAID-0");
  938.                         } else if (pcdi->ld_dtype == 2) {
  939.                             strcpy(hrec, "Chain");
  940.                         } else {
  941.                             strcpy(hrec, "???");
  942.                         }
  943.                         size = sprintf(buffer+len,
  944.                                        " Capacity [MB]:t%-6d    tType:          t%sn",
  945.                                        pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
  946.                                        hrec);
  947.                         len += size;  pos = begin + len;
  948.                     } else {
  949.                         size = sprintf(buffer+len,
  950.                                        " Slave Number: t%-2d        tStatus:        t%sn",
  951.                                        drv_no & 0x7fff, hrec);
  952.                         len += size;  pos = begin + len;
  953.                     }
  954.                     drv_no = pcdi->ld_slave;
  955.                     if (pos < offset) {
  956.                         len = 0;
  957.                         begin = pos;
  958.                     }
  959.                     if (pos > offset + length)
  960.                         goto stop_output;
  961.                 } while (drv_no != -1);
  962.                 
  963.                 if (is_mirr) {
  964.                     size = sprintf(buffer+len,
  965.                                    " Missing Drv.: t%-2d        tInvalid Drv.:  t%dn",
  966.                                    no_mdrv - j - k, k);
  967.                     len += size;  pos = begin + len;
  968.                 }
  969.                 
  970.                 if (!ha->hdr[i].is_arraydrv)
  971.                     strcpy(hrec, "--");
  972.                 else
  973.                     sprintf(hrec, "%d", ha->hdr[i].master_no);
  974.                 size = sprintf(buffer+len,
  975.                                " To Array Drv.:t%sn", hrec);
  976.                 len += size;  pos = begin + len;
  977.                 if (pos < offset) {
  978.                     len = 0;
  979.                     begin = pos;
  980.                 }
  981.                 if (pos > offset + length)
  982.                     goto stop_output;
  983.             }       
  984.             gdth_ioctl_free(hanum, buf);
  985.         
  986.             if (!flag) {
  987.                 size = sprintf(buffer+len, "n --n");
  988.                 len += size;  pos = begin + len;
  989.             }   
  990.             /* 4. about array drives */
  991.             size = sprintf(buffer+len,"nArray Drives:");
  992.             len += size;  pos = begin + len;
  993.             flag = FALSE;
  994.             buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
  995.             if (!buf) 
  996.                 goto stop_output;
  997.             for (i = 0; i < MAX_LDRIVES; ++i) {
  998.                 if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
  999.                     continue;
  1000.                 /* 4.a array drive info */
  1001.                 TRACE2(("array_info() drive no %dn",i));
  1002.                 pai = (gdth_arrayinf_str *)buf;
  1003.                 gdtcmd.Service = CACHESERVICE;
  1004.                 gdtcmd.OpCode = GDT_IOCTL;
  1005.                 gdtcmd.u.ioctl.p_param = virt_to_bus(pai);
  1006.                 gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
  1007.                 gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
  1008.                 gdtcmd.u.ioctl.channel = i;
  1009. #if LINUX_VERSION_CODE >= 0x020322
  1010.                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  1011.                 if (scp->SCp.Status == S_OK) 
  1012. #else
  1013.                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  1014.                 if (scp.SCp.Status == S_OK) 
  1015. #endif
  1016.                 {
  1017.                     if (pai->ai_state == 0)
  1018.                         strcpy(hrec, "idle");
  1019.                     else if (pai->ai_state == 2)
  1020.                         strcpy(hrec, "build");
  1021.                     else if (pai->ai_state == 4)
  1022.                         strcpy(hrec, "ready");
  1023.                     else if (pai->ai_state == 6)
  1024.                         strcpy(hrec, "fail");
  1025.                     else if (pai->ai_state == 8 || pai->ai_state == 10)
  1026.                         strcpy(hrec, "rebuild");
  1027.                     else
  1028.                         strcpy(hrec, "error");
  1029.                     if (pai->ai_ext_state & 0x10)
  1030.                         strcat(hrec, "/expand");
  1031.                     else if (pai->ai_ext_state & 0x1)
  1032.                         strcat(hrec, "/patch");
  1033.                     size = sprintf(buffer+len,
  1034.                                    "n Number:       t%-2d        tStatus:        t%sn",
  1035.                                    i,hrec);
  1036.                     len += size;  pos = begin + len;
  1037.                     flag = TRUE;
  1038.                     if (pai->ai_type == 0)
  1039.                         strcpy(hrec, "RAID-0");
  1040.                     else if (pai->ai_type == 4)
  1041.                         strcpy(hrec, "RAID-4");
  1042.                     else if (pai->ai_type == 5)
  1043.                         strcpy(hrec, "RAID-5");
  1044.                     else 
  1045.                         strcpy(hrec, "RAID-10");
  1046.                     size = sprintf(buffer+len,
  1047.                                    " Capacity [MB]:t%-6d    tType:          t%sn",
  1048.                                    pai->ai_size/(1024*1024/pai->ai_secsize),
  1049.                                    hrec);
  1050.                     len += size;  pos = begin + len;
  1051.                     if (pos < offset) {
  1052.                         len = 0;
  1053.                         begin = pos;
  1054.                     }
  1055.                     if (pos > offset + length)
  1056.                         goto stop_output;
  1057.                 }
  1058.             }
  1059.             gdth_ioctl_free(hanum, buf);
  1060.         
  1061.             if (!flag) {
  1062.                 size = sprintf(buffer+len, "n --n");
  1063.                 len += size;  pos = begin + len;
  1064.             }
  1065.             /* 5. about host drives */
  1066.             size = sprintf(buffer+len,"nHost Drives:");
  1067.             len += size;  pos = begin + len;
  1068.             flag = FALSE;
  1069.             buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
  1070.             if (!buf) 
  1071.                 goto stop_output;
  1072.             for (i = 0; i < MAX_LDRIVES; ++i) {
  1073.                 if (!ha->hdr[i].is_logdrv || 
  1074.                     (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
  1075.                     continue;
  1076.                 /* 5.a get host drive list */
  1077.                 TRACE2(("host_get() drv_no %dn",i));           
  1078.                 phg = (gdth_hget_str *)buf;
  1079.                 gdtcmd.Service = CACHESERVICE;
  1080.                 gdtcmd.OpCode = GDT_IOCTL;
  1081.                 gdtcmd.u.ioctl.p_param = virt_to_bus(phg);
  1082.                 gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
  1083.                 gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
  1084.                 gdtcmd.u.ioctl.channel = i;
  1085.                 phg->entries = MAX_HDRIVES;
  1086.                 phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 
  1087. #if LINUX_VERSION_CODE >= 0x020322
  1088.                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
  1089.                 if (scp->SCp.Status != S_OK) 
  1090. #else
  1091.                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
  1092.                 if (scp.SCp.Status != S_OK) 
  1093. #endif
  1094.                 {
  1095.                     ha->hdr[i].ldr_no = i;
  1096.                     ha->hdr[i].rw_attribs = 0;
  1097.                     ha->hdr[i].start_sec = 0;
  1098.                 } else {
  1099.                     for (j = 0; j < phg->entries; ++j) {
  1100.                         k = phg->entry[j].host_drive;
  1101.                         if (k >= MAX_LDRIVES)
  1102.                             continue;
  1103.                         ha->hdr[k].ldr_no = phg->entry[j].log_drive;
  1104.                         ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
  1105.                         ha->hdr[k].start_sec = phg->entry[j].start_sec;
  1106.                     }
  1107.                 }
  1108.             }
  1109.             gdth_ioctl_free(hanum, buf);
  1110.             for (i = 0; i < MAX_HDRIVES; ++i) {
  1111.                 if (!(ha->hdr[i].present))
  1112.                     continue;
  1113.                 
  1114.                 size = sprintf(buffer+len,
  1115.                                "n Number:       t%-2d        tArr/Log. Drive:t%dn",
  1116.                                i, ha->hdr[i].ldr_no);
  1117.                 len += size;  pos = begin + len;
  1118.                 flag = TRUE;
  1119.                 size = sprintf(buffer+len,
  1120.                                " Capacity [MB]:t%-6d    tStart Sector:  t%dn",
  1121.                                ha->hdr[i].size/2048, ha->hdr[i].start_sec);
  1122.                 len += size;  pos = begin + len;
  1123.                 if (pos < offset) {
  1124.                     len = 0;
  1125.                     begin = pos;
  1126.                 }
  1127.                 if (pos > offset + length)
  1128.                     goto stop_output;
  1129.             }
  1130.         
  1131.             if (!flag) {
  1132.                 size = sprintf(buffer+len, "n --n");
  1133.                 len += size;  pos = begin + len;
  1134.             }
  1135.         }
  1136.         /* controller events */
  1137.         size = sprintf(buffer+len,"nController Events:n");
  1138.         len += size;  pos = begin + len;
  1139.         for (id = -1;;) {
  1140.             id = gdth_read_event(ha, id, &estr);
  1141.             if (estr.event_source == 0)
  1142.                 break;
  1143.             if (estr.event_data.eu.driver.ionode == hanum &&
  1144.                 estr.event_source == ES_ASYNC) { 
  1145.                 gdth_log_event(&estr.event_data, hrec);
  1146.                 do_gettimeofday(&tv);
  1147.                 sec = (int)(tv.tv_sec - estr.first_stamp);
  1148.                 if (sec < 0) sec = 0;
  1149.                 size = sprintf(buffer+len," date- %02d:%02d:%02dt%sn",
  1150.                                sec/3600, sec%3600/60, sec%60, hrec);
  1151.                 len += size;  pos = begin + len;
  1152.                 if (pos < offset) {
  1153.                     len = 0;
  1154.                     begin = pos;
  1155.                 }
  1156.                 if (pos > offset + length)
  1157.                     goto stop_output;
  1158.             }
  1159.             if (id == -1)
  1160.                 break;
  1161.         }
  1162.     } else {
  1163.         /* request from tool (GDTMON,..) */
  1164.         piord = (gdth_iord_str *)ha->pscratch;
  1165.         if (piord == NULL)
  1166.             goto stop_output;
  1167.         length = piord->size;
  1168.         memcpy(buffer+len, (char *)piord, length);
  1169.         gdth_ioctl_free(hanum, ha->pscratch);
  1170.         len = length; 
  1171.     }
  1172. stop_output:
  1173. #if LINUX_VERSION_CODE >= 0x020322
  1174.     scsi_release_command(scp);
  1175.     scsi_free_host_dev(sdev);
  1176. #endif
  1177.     *start = buffer +(offset-begin);
  1178.     len -= (offset-begin);
  1179.     if (len > length)
  1180.         len = length;
  1181.     TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %dn",
  1182.             len,(int)pos,(int)begin,(int)offset,length,size));
  1183.     return(len);
  1184. }
  1185. static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, 
  1186.                         char *cmnd, int timeout)
  1187. {
  1188.     unsigned bufflen;
  1189. #if LINUX_VERSION_CODE >= 0x020407
  1190.     DECLARE_COMPLETION(wait);
  1191. #elif LINUX_VERSION_CODE >= 0x020322
  1192.     DECLARE_MUTEX_LOCKED(sem);
  1193. #else
  1194.     struct semaphore sem = MUTEX_LOCKED;
  1195. #endif
  1196.     TRACE2(("gdth_do_cmd()n"));
  1197.     if (gdtcmd != NULL) { 
  1198.         scp->SCp.this_residual = IOCTL_PRI;
  1199.         bufflen = sizeof(gdth_cmd_str);
  1200.     } else {
  1201.         scp->SCp.this_residual = DEFAULT_PRI;
  1202.         bufflen = 0;
  1203.     }
  1204.     scp->request.rq_status = RQ_SCSI_BUSY;
  1205. #if LINUX_VERSION_CODE >= 0x020407
  1206.     scp->request.waiting = &wait;
  1207.     scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
  1208.     wait_for_completion(&wait);
  1209. #else
  1210.     scp->request.sem = &sem;
  1211. #if LINUX_VERSION_CODE >= 0x020322
  1212.     scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
  1213. #else
  1214.     GDTH_LOCK_SCSI_DOCMD();
  1215.     scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
  1216.     GDTH_UNLOCK_SCSI_DOCMD();
  1217. #endif
  1218.     down(&sem);
  1219. #endif
  1220. }
  1221. void gdth_scsi_done(Scsi_Cmnd *scp)
  1222. {
  1223.     TRACE2(("gdth_scsi_done()n"));
  1224.     scp->request.rq_status = RQ_SCSI_DONE;
  1225. #if LINUX_VERSION_CODE >= 0x020407
  1226.     if (scp->request.waiting != NULL)
  1227.         complete(scp->request.waiting);
  1228. #else
  1229.     if (scp->request.sem != NULL)
  1230.         up(scp->request.sem);
  1231. #endif
  1232. }
  1233. static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch)
  1234. {
  1235.     gdth_ha_str *ha;
  1236.     ulong flags;
  1237.     char *ret_val;
  1238.     if (size == 0 || size > GDTH_SCRATCH)
  1239.         return FALSE;
  1240.     ha = HADATA(gdth_ctr_tab[hanum]);
  1241.     GDTH_LOCK_HA(ha, flags);
  1242.     if (scratch) { 
  1243.         if (!ha->scratch_busy) {
  1244.             ha->scratch_busy = TRUE;
  1245.             ret_val = ha->pscratch;
  1246.         } else
  1247.             ret_val = NULL;
  1248.     } else {
  1249. #if LINUX_VERSION_CODE >= 0x020322
  1250.         ret_val = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
  1251.                                             GDTH_SCRATCH_ORD);
  1252. #else
  1253.         ret_val = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
  1254. #endif
  1255.     }
  1256.     GDTH_UNLOCK_HA(ha, flags);
  1257.     return ret_val;
  1258. }
  1259. static void gdth_ioctl_free(int hanum, char *buf)
  1260. {
  1261.     gdth_ha_str *ha;
  1262.     ulong flags;
  1263.     ha = HADATA(gdth_ctr_tab[hanum]);
  1264.     GDTH_LOCK_HA(ha, flags);
  1265.     if (buf == ha->pscratch) {
  1266.         ha->scratch_busy = FALSE;
  1267.     } else {
  1268. #if LINUX_VERSION_CODE >= 0x020322
  1269.         free_pages((unsigned long)buf, GDTH_SCRATCH_ORD);
  1270. #else
  1271.         scsi_init_free((void *)buf, GDTH_SCRATCH);
  1272. #endif
  1273.     }
  1274.     GDTH_UNLOCK_HA(ha, flags);
  1275. }
  1276. static int gdth_ioctl_check_bin(int hanum, ushort size)
  1277. {
  1278.     gdth_ha_str *ha;
  1279.     ulong flags;
  1280.     int ret_val;
  1281.     ha = HADATA(gdth_ctr_tab[hanum]);
  1282.     GDTH_LOCK_HA(ha, flags);
  1283.     ret_val = FALSE;
  1284.     if (ha->scratch_busy) {
  1285.         if (((gdth_iord_str *)ha->pscratch)->size == (ulong32)size)
  1286.             ret_val = TRUE;
  1287.     }
  1288.     GDTH_UNLOCK_HA(ha, flags);
  1289.     return ret_val;
  1290. }
  1291. static void gdth_wait_completion(int hanum, int busnum, int id)
  1292. {
  1293.     gdth_ha_str *ha;
  1294.     ulong flags;
  1295.     int i;
  1296.     Scsi_Cmnd *scp;
  1297.     unchar b;
  1298.     ha = HADATA(gdth_ctr_tab[hanum]);
  1299.     GDTH_LOCK_HA(ha, flags);
  1300.     for (i = 0; i < GDTH_MAXCMDS; ++i) {
  1301.         scp = ha->cmd_tab[i].cmnd;
  1302.         b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
  1303.         if (!SPECIAL_SCP(scp) && scp->target == (unchar)id && 
  1304.             b == (unchar)busnum) {
  1305.             scp->SCp.have_data_in = 0;
  1306.             GDTH_UNLOCK_HA(ha, flags);
  1307.             while (!scp->SCp.have_data_in)
  1308.                 barrier();
  1309.             GDTH_LOCK_SCSI_DONE(flags);
  1310.             scp->scsi_done(scp);
  1311.             GDTH_UNLOCK_SCSI_DONE(flags);
  1312.         GDTH_LOCK_HA(ha, flags);
  1313.         }
  1314.     }
  1315.     GDTH_UNLOCK_HA(ha, flags);
  1316. }
  1317. static void gdth_stop_timeout(int hanum, int busnum, int id)
  1318. {
  1319.     gdth_ha_str *ha;
  1320.     ulong flags;
  1321.     Scsi_Cmnd *scp;
  1322.     unchar b;
  1323.     ha = HADATA(gdth_ctr_tab[hanum]);
  1324.     GDTH_LOCK_HA(ha, flags);
  1325.     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
  1326.         b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
  1327.         if (scp->target == (unchar)id && b == (unchar)busnum) {
  1328.             TRACE2(("gdth_stop_timeout(): update_timeout()n"));
  1329.             scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
  1330.         }
  1331.     }
  1332.     GDTH_UNLOCK_HA(ha, flags);
  1333. }
  1334. static void gdth_start_timeout(int hanum, int busnum, int id)
  1335. {
  1336.     gdth_ha_str *ha;
  1337.     ulong flags;
  1338.     Scsi_Cmnd *scp;
  1339.     unchar b;
  1340.     ha = HADATA(gdth_ctr_tab[hanum]);
  1341.     GDTH_LOCK_HA(ha, flags);
  1342.     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
  1343.         b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
  1344.         if (scp->target == (unchar)id && b == (unchar)busnum) {
  1345.             TRACE2(("gdth_start_timeout(): update_timeout()n"));
  1346.             gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
  1347.         }
  1348.     }
  1349.     GDTH_UNLOCK_HA(ha, flags);
  1350. }
  1351. static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
  1352. {
  1353.     int oldto;
  1354.     oldto = scp->timeout_per_command;
  1355.     scp->timeout_per_command = timeout;
  1356. #if LINUX_VERSION_CODE >= 0x02014B
  1357.     if (timeout == 0) {
  1358.         del_timer(&scp->eh_timeout);
  1359.         scp->eh_timeout.data = (unsigned long) NULL;
  1360.         scp->eh_timeout.expires = 0;
  1361.     } else {
  1362.         if (scp->eh_timeout.data != (unsigned long) NULL) 
  1363.             del_timer(&scp->eh_timeout);
  1364.         scp->eh_timeout.data = (unsigned long) scp;
  1365.         scp->eh_timeout.expires = jiffies + timeout;
  1366.         add_timer(&scp->eh_timeout);
  1367.     }
  1368. #else
  1369.     if (timeout > 0) {
  1370.         if (timer_table[SCSI_TIMER].expires == 0) {
  1371.             timer_table[SCSI_TIMER].expires = jiffies + timeout;
  1372.             timer_active |= 1 << SCSI_TIMER;
  1373.         } else {
  1374.             if (time_before(jiffies + timeout, timer_table[SCSI_TIMER].expires))
  1375.                 timer_table[SCSI_TIMER].expires = jiffies + timeout;
  1376.         }
  1377.     }
  1378. #endif
  1379.     return oldto;
  1380. }