diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1995-11-14 08:00:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1995-11-14 08:00:00 +0000 |
commit | e7c2a72e2680827d6a733931273a93461c0d8d1b (patch) | |
tree | c9abeda78ef7504062bb2e816bcf3e3c9d680112 /drivers/scsi/hosts.c | |
parent | ec6044459060a8c9ce7f64405c465d141898548c (diff) |
Import of Linux/MIPS 1.3.0
Diffstat (limited to 'drivers/scsi/hosts.c')
-rw-r--r-- | drivers/scsi/hosts.c | 171 |
1 files changed, 124 insertions, 47 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 9488c1f19..eb7ba3789 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -1,7 +1,10 @@ /* - * hosts.c Copyright (C) 1992 Drew Eckhardt - * mid to lowlevel SCSI driver interface by - * Drew Eckhardt + * hosts.c Copyright (C) 1992 Drew Eckhardt + * Copyright (C) 1993, 1994, 1995 Eric Youngdale + * + * mid to lowlevel SCSI driver interface + * Initial versions: Drew Eckhardt + * Subsequent revisions: Eric Youngdale * * <drew@colorado.edu> */ @@ -10,16 +13,18 @@ /* * This file contains the medium level SCSI * host interface initialization, as well as the scsi_hosts array of SCSI - * hosts currently present in the system. + * hosts currently present in the system. */ #include <linux/config.h> #include "../block/blk.h" #include <linux/kernel.h> #include <linux/string.h> +#include <linux/mm.h> + #include "scsi.h" -#ifndef NULL +#ifndef NULL #define NULL 0L #endif @@ -47,10 +52,14 @@ #include "buslogic.h" #endif +#ifdef CONFIG_SCSI_EATA_DMA +#include "eata_dma.h" +#endif + #ifdef CONFIG_SCSI_U14_34F #include "u14-34f.h" #endif - + #ifdef CONFIG_SCSI_FUTURE_DOMAIN #include "fdomain.h" #endif @@ -94,7 +103,7 @@ #ifdef CONFIG_SCSI_EATA #include "eata.h" #endif - + #ifdef CONFIG_SCSI_DEBUG #include "scsi_debug.h" #endif @@ -104,9 +113,9 @@ static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hos */ /* - * The scsi host entries should be in the order you wish the + * The scsi host entries should be in the order you wish the * cards to be detected. A driver may appear more than once IFF - * it can deal with being detected (and therefore initialized) + * it can deal with being detected (and therefore initialized) * with more than one simultaneous host number, can handle being * reentrant, etc. * @@ -122,9 +131,9 @@ static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/hos NULL, NULL, 0, 0, 0, 0, 0, 0} /* - * When figure is run, we don't want to link to any object code. Since - * the macro for each host will contain function pointers, we cannot - * use it and instead must use a "blank" that does no such + * When figure is run, we don't want to link to any object code. Since + * the macro for each host will contain function pointers, we cannot + * use it and instead must use a "blank" that does no such * idiocy. */ @@ -161,7 +170,7 @@ static Scsi_Host_Template builtin_scsi_hosts[] = IN2000, #endif #ifdef CONFIG_SCSI_GENERIC_NCR5380 - GENERIC_NCR5380, + GENERIC_NCR5380, #endif #ifdef CONFIG_SCSI_QLOGIC QLOGIC, @@ -173,11 +182,14 @@ static Scsi_Host_Template builtin_scsi_hosts[] = SEAGATE_ST0X, #endif #ifdef CONFIG_SCSI_T128 - TRANTOR_T128, + TRANTOR_T128, #endif #ifdef CONFIG_SCSI_NCR53C7xx NCR53c7xx, #endif +#ifdef CONFIG_SCSI_EATA_DMA + EATA_DMA, +#endif #ifdef CONFIG_SCSI_7000FASST WD7000, #endif @@ -192,31 +204,34 @@ static Scsi_Host_Template builtin_scsi_hosts[] = #define MAX_SCSI_HOSTS (sizeof(builtin_scsi_hosts) / sizeof(Scsi_Host_Template)) /* - * Our semaphores and timeout counters, where size depends on MAX_SCSI_HOSTS here. + * Our semaphores and timeout counters, where size depends on MAX_SCSI_HOSTS here. */ struct Scsi_Host * scsi_hostlist = NULL; struct Scsi_Device_Template * scsi_devicelist; int max_scsi_hosts = 0; -static int next_host = 0; +int next_scsi_host = 0; void scsi_unregister(struct Scsi_Host * sh){ struct Scsi_Host * shpnt; - int j; - - j = sh->extra_bytes; if(scsi_hostlist == sh) - scsi_hostlist = NULL; + scsi_hostlist = sh->next; else { shpnt = scsi_hostlist; while(shpnt->next != sh) shpnt = shpnt->next; shpnt->next = shpnt->next->next; }; - next_host--; - scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + j); + + /* If we are removing the last host registered, it is safe to reuse + its host number (this avoids "holes" at boot time) (DB) */ + if (max_scsi_hosts == next_scsi_host && !scsi_loadable_module_flag) + max_scsi_hosts--; + + next_scsi_host--; + scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + sh->extra_bytes); } /* We call this when we come across a new host adapter. We only do this @@ -225,21 +240,28 @@ scsi_unregister(struct Scsi_Host * sh){ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ struct Scsi_Host * retval, *shpnt; - retval = (struct Scsi_Host *)scsi_init_malloc(sizeof(struct Scsi_Host) + j); + retval = (struct Scsi_Host *)scsi_init_malloc(sizeof(struct Scsi_Host) + j, + (tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC); retval->host_busy = 0; retval->block = NULL; + retval->wish_block = 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 = next_host++; - retval->host_queue = NULL; - retval->host_wait = NULL; - retval->last_reset = 0; + retval->host_no = max_scsi_hosts++; /* never reuse host_no (DB) */ + next_scsi_host++; + retval->host_queue = NULL; + retval->host_wait = NULL; + retval->last_reset = 0; retval->irq = 0; - retval->hostt = tpnt; + retval->dma_channel = 0xff; + retval->io_port = 0; + retval->forbidden_addr = 0; + retval->forbidden_size = 0; + retval->hostt = tpnt; retval->next = NULL; #ifdef DEBUG - printk("Register %x %x: %d\n", retval, retval->hostt, j); + printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j); #endif /* The next four are the default values which can be overridden @@ -247,6 +269,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ retval->this_id = tpnt->this_id; retval->can_queue = tpnt->can_queue; retval->sg_tablesize = tpnt->sg_tablesize; + retval->cmd_per_lun = tpnt->cmd_per_lun; retval->unchecked_isa_dma = tpnt->unchecked_isa_dma; if(!scsi_hostlist) @@ -273,43 +296,56 @@ scsi_register_device(struct Scsi_Device_Template * sdpnt) unsigned int scsi_init() { static int called = 0; - int i, j, count, pcount; + int i, pcount; Scsi_Host_Template * tpnt; - count = 0; + struct Scsi_Host * shpnt; + const char * name; if(called) return 0; - called = 1; + called = 1; for (tpnt = &builtin_scsi_hosts[0], i = 0; i < MAX_SCSI_HOSTS; ++i, tpnt++) { /* - * Initialize our semaphores. -1 is interpreted to mean + * Initialize our semaphores. -1 is interpreted to mean * "inactive" - where as 0 will indicate a time out condition. - */ - - pcount = next_host; - if ((tpnt->detect) && - (tpnt->present = + */ + + pcount = next_scsi_host; + if ((tpnt->detect) && + (tpnt->present = tpnt->detect(tpnt))) - { + { /* The only time this should come up is when people use some kind of patched driver of some kind or another. */ - if(pcount == next_host) { + if(pcount == next_scsi_host) { if(tpnt->present > 1) panic("Failure to register low-level scsi driver"); /* The low-level driver failed to register a driver. We - can do this now. */ + can do this now. */ scsi_register(tpnt,0); }; tpnt->next = scsi_hosts; scsi_hosts = tpnt; - for(j = 0; j < tpnt->present; j++) - printk ("scsi%d : %s\n", - count++, tpnt->name); } } - printk ("scsi : %d hosts.\n", count); - + + + for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) + { + if(shpnt->hostt->info) + name = shpnt->hostt->info(shpnt); + else + name = shpnt->hostt->name; + printk ("scsi%d : %s\n", /* And print a little message */ + shpnt->host_no, name); + } + + printk ("scsi : %d host%s.\n", next_scsi_host, + (next_scsi_host == 1) ? "" : "s"); + + scsi_make_blocked_list(); + /* Now attach the high level drivers */ #ifdef CONFIG_BLK_DEV_SD scsi_register_device(&sd_template); @@ -324,6 +360,47 @@ unsigned int scsi_init() scsi_register_device(&sg_template); #endif - max_scsi_hosts = count; +#if 0 + max_scsi_hosts = next_scsi_host; +#endif return 0; } + + +void scsi_mem_init(unsigned long memory_end) +{ + struct Scsi_Host *Host; + long High8, Low24; + for (Host = scsi_hostlist; Host != NULL; Host = Host->next) { + if (Host->forbidden_addr > 0 && Host->forbidden_size > 0) { + for (High8 = 1<<24; High8 < memory_end; High8 += 1<<24) { + for (Low24 = Host->forbidden_addr; + Low24 < Host->forbidden_addr + Host->forbidden_size; + Low24 += PAGE_SIZE) { + unsigned long ForbiddenAddress = High8 + Low24; + if (ForbiddenAddress >= memory_end) goto next_host; + mem_map[MAP_NR(ForbiddenAddress)] = MAP_PAGE_RESERVED; + } + } + } + next_host: + continue; + } +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */ |