OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [gdth_proc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.