diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-24 00:12:35 +0000 |
commit | 482368b1a8e45430672c58c9a42e7d2004367126 (patch) | |
tree | ce2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /drivers/scsi/hosts.c | |
parent | e4d0251c6f56ab2e191afb70f80f382793e23f74 (diff) |
Merge with 2.3.47. Guys, this is buggy as shit. You've been warned.
Diffstat (limited to 'drivers/scsi/hosts.c')
-rw-r--r-- | drivers/scsi/hosts.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 500c19b09..321b783a5 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -681,6 +681,7 @@ static Scsi_Host_Template builtin_scsi_hosts[] = * MAX_SCSI_HOSTS here. */ +Scsi_Host_Name * scsi_host_no_list = NULL; struct Scsi_Host * scsi_hostlist = NULL; struct Scsi_Device_Template * scsi_devicelist = NULL; @@ -690,7 +691,8 @@ int next_scsi_host = 0; void scsi_unregister(struct Scsi_Host * sh){ struct Scsi_Host * shpnt; - + Scsi_Host_Name *shn; + if(scsi_hostlist == sh) scsi_hostlist = sh->next; else { @@ -698,6 +700,16 @@ scsi_unregister(struct Scsi_Host * sh){ while(shpnt->next != sh) shpnt = shpnt->next; shpnt->next = shpnt->next->next; } + + /* + * We have to unregister the host from the scsi_host_no_list as well. + * Decide by the host_no not by the name because most host drivers are + * able to handle more than one adapters from the same kind (or family). + */ + for ( shn=scsi_host_no_list; shn && (sh->host_no != shn->host_no); + shn=shn->next); + if (shn) shn->host_registered = 0; + /* else {} : This should not happen, we should panic here... */ /* If we are removing the last host registered, it is safe to reuse * its host number (this avoids "holes" at boot time) (DB) @@ -724,16 +736,50 @@ scsi_unregister(struct Scsi_Host * sh){ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ struct Scsi_Host * retval, *shpnt; + Scsi_Host_Name *shn, *shn2; + int new = 1; retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j, (tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC); memset(retval, 0, sizeof(struct Scsi_Host) + j); + + /* trying to find a reserved entry (host_no) */ + for (shn = scsi_host_no_list;shn;shn = shn->next) + if (!(shn->host_registered) && shn->loaded_as_module && tpnt->proc_dir && + tpnt->proc_dir->name && !strncmp(tpnt->proc_dir->name, shn->name, strlen(tpnt->proc_dir->name))) { + new = 0; + retval->host_no = shn->host_no; + shn->host_registered = 1; + shn->loaded_as_module = scsi_loadable_module_flag; + break; + } atomic_set(&retval->host_active,0); retval->host_busy = 0; retval->host_failed = 0; if(j > 0xffff) panic("Too many extra bytes requested\n"); retval->extra_bytes = j; retval->loaded_as_module = scsi_loadable_module_flag; - retval->host_no = max_scsi_hosts++; /* never reuse host_no (DB) */ + if (new) { + int len = 0; + shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC); + if (tpnt->proc_dir) + len = strlen(tpnt->proc_dir->name); + shn->name = kmalloc(len+1, GFP_ATOMIC); + if (tpnt->proc_dir) + strncpy(shn->name, tpnt->proc_dir->name, len); + shn->name[len] = 0; + shn->host_no = max_scsi_hosts++; + shn->host_registered = 1; + shn->loaded_as_module = scsi_loadable_module_flag; + shn->next = NULL; + if (scsi_host_no_list) { + for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next) + ; + shn2->next = shn; + } + else + scsi_host_no_list = shn; + retval->host_no = shn->host_no; + } next_scsi_host++; retval->host_queue = NULL; init_waitqueue_head(&retval->host_wait); @@ -747,6 +793,14 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ retval->max_id = 8; retval->max_lun = 8; + /* + * All drivers right now should be able to handle 12 byte commands. + * Every so often there are requests for 16 byte commands, but individual + * low-level drivers need to certify that they actually do something + * sensible with such commands. + */ + retval->max_cmd_len = 12; + retval->unique_id = 0; retval->io_port = 0; retval->hostt = tpnt; @@ -757,6 +811,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ retval->host_blocked = FALSE; + retval->host_self_blocked = FALSE; #ifdef DEBUG printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j); |