extractedLnx/linux-2.6.9/drivers/scsi/gdth.c_gdth_next.c
static void gdth_next(int hanum)
{
register gdth_ha_str *ha;
register Scsi_Cmnd *pscp;
register Scsi_Cmnd *nscp;
unchar b, t, l, firsttime;
unchar this_cmd, next_cmd;
ulong flags = 0;
int cmd_index;
TRACE(("gdth_next() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
if (!gdth_polling)
GDTH_LOCK_HA(ha, flags);
ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
this_cmd = firsttime = TRUE;
next_cmd = gdth_polling ? FALSE:TRUE;
cmd_index = 0;
for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
t = nscp->device->id;
l = nscp->device->lun;
#else
b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
t = nscp->target;
l = nscp->lun;
#endif
if (nscp->SCp.this_residual >= DEFAULT_PRI) {
if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
(b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
continue;
}
if (firsttime) {
if (gdth_test_busy(hanum)) { /* controller busy ? */
TRACE(("gdth_next() controller %d busy !\n",hanum));
if (!gdth_polling) {
GDTH_UNLOCK_HA(ha, flags);
return;
}
while (gdth_test_busy(hanum))
gdth_delay(1);
}
firsttime = FALSE;
}
if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) {
if (nscp->SCp.phase == -1) {
nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */
if (nscp->cmnd[0] == TEST_UNIT_READY) {
TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
b, t, l));
/* TEST_UNIT_READY -> set scan mode */
if ((ha->scan_mode & 0x0f) == 0) {
if (b == 0 && t == 0 && l == 0) {
ha->scan_mode |= 1;
TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
}
} else if ((ha->scan_mode & 0x0f) == 1) {
if (b == 0 && ((t == 0 && l == 1) ||
(t == 1 && l == 0))) {
nscp->SCp.sent_command = GDT_SCAN_START;
nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8)
| SCSIRAWSERVICE;
ha->scan_mode = 0x12;
TRACE2(("Scan mode: 0x%x (SCAN_START)\n",
ha->scan_mode));
} else {
ha->scan_mode &= 0x10;
TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
}
} else if (ha->scan_mode == 0x12) {
if (b == ha->bus_cnt && t == ha->tid_cnt-1) {
nscp->SCp.phase = SCSIRAWSERVICE;
nscp->SCp.sent_command = GDT_SCAN_END;
ha->scan_mode &= 0x10;
TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
ha->scan_mode));
}
}
}
if (b == ha->virt_bus && nscp->cmnd[0] != INQUIRY &&
nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE &&
(ha->hdr[t].cluster_type & CLUSTER_DRIVE)) {
/* always GDT_CLUST_INFO! */
nscp->SCp.sent_command = GDT_CLUST_INFO;
}
}
}
if (nscp->SCp.sent_command != -1) {
if ((nscp->SCp.phase & 0xff) == CACHESERVICE) {
if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
this_cmd = FALSE;
next_cmd = FALSE;
} else if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
this_cmd = FALSE;
next_cmd = FALSE;
} else {
memset((char*)nscp->sense_buffer,0,16);
nscp->sense_buffer[0] = 0x70;
nscp->sense_buffer[2] = NOT_READY;
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
}
} else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
this_cmd = FALSE;
next_cmd = FALSE;
} else if (b != ha->virt_bus) {
if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b))))
this_cmd = FALSE;
else
ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
} else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) {
TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
nscp->cmnd[0], b, t, l));
nscp->result = DID_BAD_TARGET << 16;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
} else {
switch (nscp->cmnd[0]) {
case TEST_UNIT_READY:
case INQUIRY:
case REQUEST_SENSE:
case READ_CAPACITY:
case VERIFY:
case START_STOP:
case MODE_SENSE:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case SERVICE_ACTION_IN:
#endif
TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
nscp->cmnd[4],nscp->cmnd[5]));
if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) {
/* return UNIT_ATTENTION */
TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
nscp->cmnd[0], t));
ha->hdr[t].media_changed = FALSE;
memset((char*)nscp->sense_buffer,0,16);
nscp->sense_buffer[0] = 0x70;
nscp->sense_buffer[2] = UNIT_ATTENTION;
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
} else if (gdth_internal_cache_cmd(hanum,nscp)) {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
break;
case ALLOW_MEDIUM_REMOVAL:
TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
nscp->cmnd[4],nscp->cmnd[5]));
if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) {
TRACE(("Prevent r. nonremov. drive->do nothing\n"));
nscp->result = DID_OK << 16;
nscp->sense_buffer[0] = 0;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
} else {
nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
TRACE(("Prevent/allow r. %d rem. drive %d\n",
nscp->cmnd[4],nscp->cmnd[3]));
if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
this_cmd = FALSE;
}
break;
case RESERVE:
case RELEASE:
TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ?
"RESERVE" : "RELEASE"));
if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
this_cmd = FALSE;
break;
case READ_6:
case WRITE_6:
case READ_10:
case WRITE_10:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
case READ_16:
case WRITE_16:
#endif
if (ha->hdr[t].media_changed) {
/* return UNIT_ATTENTION */
TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
nscp->cmnd[0], t));
ha->hdr[t].media_changed = FALSE;
memset((char*)nscp->sense_buffer,0,16);
nscp->sense_buffer[0] = 0x70;
nscp->sense_buffer[2] = UNIT_ATTENTION;
nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
} else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
this_cmd = FALSE;
break;
default:
TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0],
nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
nscp->cmnd[4],nscp->cmnd[5]));
printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n",
hanum, nscp->cmnd[0]);
nscp->result = DID_ABORT << 16;
if (!nscp->SCp.have_data_in)
nscp->SCp.have_data_in++;
else {
if (!gdth_polling)
GDTH_UNLOCK_HA(ha,flags);
/* io_request_lock already active ! */
nscp->scsi_done(nscp);
if (!gdth_polling)
GDTH_LOCK_HA(ha,flags);
}
break;
}
}
if (!this_cmd)
break;
if (nscp == ha->req_first)
ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
else
pscp->SCp.ptr = nscp->SCp.ptr;
if (!next_cmd)
break;
}
if (ha->cmd_cnt > 0) {
gdth_release_event(hanum);
}
if (!gdth_polling)
GDTH_UNLOCK_HA(ha, flags);
if (gdth_polling && ha->cmd_cnt > 0) {
if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
printk("GDT-HA %d: Command %d timed out !\n",
hanum,cmd_index);
}
}
Generated by GNU enscript 1.6.4.