From fb3ed0dc9690ef62209db23d60ab415511d6734f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:09:45 -0500 Subject: [PATCH] Import 1.1.68 --- CREDITS | 7 + Makefile | 2 +- drivers/block/cdu31a.c | 2 +- drivers/char/console.c | 14 +- drivers/net/MODULES | 1 + drivers/net/eexpress.c | 38 ++ drivers/net/plip.c | 2 +- drivers/scsi/53c7,8xx.c | 6 +- drivers/scsi/53c7,8xx.h | 5 +- drivers/scsi/NCR5380.c | 2 +- drivers/scsi/aha152x.c | 16 +- drivers/scsi/aha152x.h | 4 +- drivers/scsi/aha1542.c | 145 +++++++- drivers/scsi/aha1542.h | 6 +- drivers/scsi/aha1740.c | 10 +- drivers/scsi/aha1740.h | 7 +- drivers/scsi/aha274x.c | 8 +- drivers/scsi/aha274x.h | 5 +- drivers/scsi/buslogic.c | 753 ++++++++++++++++++++++---------------- drivers/scsi/buslogic.h | 38 +- drivers/scsi/eata.c | 6 +- drivers/scsi/eata.h | 6 +- drivers/scsi/fdomain.c | 12 +- drivers/scsi/fdomain.h | 6 +- drivers/scsi/g_NCR5380.h | 5 +- drivers/scsi/hosts.c | 1 + drivers/scsi/hosts.h | 21 +- drivers/scsi/in2000.c | 12 +- drivers/scsi/in2000.h | 14 +- drivers/scsi/pas16.c | 13 - drivers/scsi/pas16.h | 5 +- drivers/scsi/qlogic.c | 4 +- drivers/scsi/qlogic.h | 3 +- drivers/scsi/scsi.c | 54 ++- drivers/scsi/scsi.h | 2 + drivers/scsi/scsi_debug.h | 5 +- drivers/scsi/scsi_ioctl.c | 17 +- drivers/scsi/sd.c | 3 + drivers/scsi/sd.h | 1 + drivers/scsi/seagate.c | 4 +- drivers/scsi/seagate.h | 4 +- drivers/scsi/sg.c | 4 + drivers/scsi/sg.h | 3 +- drivers/scsi/sr.c | 17 +- drivers/scsi/t128.c | 13 - drivers/scsi/t128.h | 5 +- drivers/scsi/u14-34f.c | 6 +- drivers/scsi/u14-34f.h | 4 +- drivers/scsi/ultrastor.c | 4 +- drivers/scsi/ultrastor.h | 6 +- drivers/scsi/wd7000.c | 14 +- drivers/scsi/wd7000.h | 5 +- fs/locks.c | 2 +- fs/proc/array.c | 2 +- fs/umsdos/emd.c | 13 +- include/asm-i386/dma.h | 3 + include/linux/inet.h | 9 +- include/linux/ioport.h | 2 + include/linux/ip.h | 4 +- include/linux/mm.h | 5 + include/linux/tcp.h | 2 +- init/main.c | 4 + kernel/ioport.c | 10 + modules/NET_MODULES | 2 +- net/inet/proc.c | 2 +- net/inet/sock.c | 2 +- 66 files changed, 878 insertions(+), 534 deletions(-) diff --git a/CREDITS b/CREDITS index 77b5748fa3ef..85510e49aab9 100644 --- a/CREDITS +++ b/CREDITS @@ -539,6 +539,13 @@ S: Ormond S: Victoria 3163 S: Australia +N: Pauline Middelink +E: middelin@polyware.iaf.nl +D: General low-level bug fixes, /proc fixes, identd support +S: Boterkorfhoek 34 +S: 7546 JA Enschede +S: Netherlands + N: Rick Miller E: rick@discus.mil.wi.us D: Linux Device Registrar (Major/minor numbers), "au-play", "bwBASIC" diff --git a/Makefile b/Makefile index d4820462cd41..203a9b3dbfb9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 67 +SUBLEVEL = 68 ARCH = i386 diff --git a/drivers/block/cdu31a.c b/drivers/block/cdu31a.c index b7825abf9265..e4d789e4d9cc 100644 --- a/drivers/block/cdu31a.c +++ b/drivers/block/cdu31a.c @@ -2773,7 +2773,7 @@ cdu31a_setup(char *strings, { irq_used = ints[2]; } - if (*strings != '\0') + if ((strings != NULL) && (*strings != '\0')) { if (strcmp(strings, "PAS") == 0) { diff --git a/drivers/char/console.c b/drivers/char/console.c index a12b321b452f..7a48e787167e 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -2106,7 +2106,7 @@ void update_screen(int new_console) } lock = 1; #ifdef CONFIG_SELECTION - highlight_pointer(fg_console,-1); + clear_selection(); #endif /* CONFIG_SELECTION */ if (!console_blanked) get_scrmem(fg_console); @@ -2148,7 +2148,7 @@ int do_screendump(int arg, int mode) /* mode 0 needs 2+wd*ht, modes 1 and 2 need 4+2*wd*ht */ chcount=video_num_columns*video_num_lines; l = verify_area(mode==2 ? VERIFY_READ :VERIFY_WRITE, - buf, (2+chcount)*(1+mode!=0)); + buf, (2+chcount)*(mode ? 2 : 1)); if (l) return l; if (mode<2) { @@ -2162,12 +2162,14 @@ int do_screendump(int arg, int mode) put_fs_byte(*sptr++,buf++); break; case 1: +#ifdef CONFIG_SELECTION + clear_selection(); +#endif put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++); memcpy_tofs(buf,(char *)origin,2*chcount); break; case 2: - buf+=2; /* skip the the numnber 9 and console number */ - x=get_fs_byte(buf++); y=get_fs_byte(buf++); + buf+=4; /* ioctl#, console#, x,y */ memcpy_fromfs((char *)origin,buf,2*chcount); break; } @@ -2356,7 +2358,6 @@ int set_selection(const int arg, struct tty_struct *tty) case 3: /* pointer highlight */ if (sel_cons != currcons) { - highlight_pointer(sel_cons,-1); clear_selection(); sel_cons = currcons; } @@ -2491,7 +2492,8 @@ static void clear_selection() */ #define colourmap ((char *)0xa0000) -/* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */ +/* Pauline Middelink reports that we + should use 0xA0000 for the bwmap as well.. */ #define blackwmap ((char *)0xa0000) #define cmapsz 8192 #define seq_port_reg (0x3c4) diff --git a/drivers/net/MODULES b/drivers/net/MODULES index d9c8ca454ca8..6ef0c7d3b1f9 100644 --- a/drivers/net/MODULES +++ b/drivers/net/MODULES @@ -3,5 +3,6 @@ MODULES = \ de600.o \ de620.o \ 3c501.o \ + eexpress.o \ plip.o \ 8390.o diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index dde116f113c1..ace82ca4e676 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -17,6 +17,8 @@ Move the theory of operation and memory map documentation. Rework the board error reset The statistics need to be updated correctly. + + Modularized my Pauline Middelink */ static char *version = @@ -53,6 +55,10 @@ static char *version = #include #include #include +#ifdef MODULE +#include +#include "../../tools/version.h" +#endif #include @@ -435,6 +441,9 @@ eexp_open(struct device *dev) dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif return 0; } @@ -647,6 +656,9 @@ eexp_close(struct device *dev) /* Update the statistics here. */ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif return 0; } @@ -981,6 +993,32 @@ eexp_rx(struct device *dev) outw(saved_write_ptr, ioaddr + WRITE_PTR); } +#ifdef MODULE +char kernel_version[] = UTS_RELEASE; +static struct device dev_eexpress = { + " " /*"eexpress"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe }; + +int +init_module(void) +{ + if (register_netdev(&dev_eexpress) != 0) + return -EIO; + return 0; +} + +void +cleanup_module(void) +{ + if (MOD_IN_USE) + printk("express: device busy, remove delayed\n"); + else + { + unregister_netdev(&dev_eexpress); + kfree_s(dev_eexpress.priv,sizeof(struct net_local)); + dev_eexpress.priv=NULL; + } +} +#endif /* MODULE */ /* * Local variables: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c eexpress.c" diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 63de01bf0280..f54135a47247 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -545,7 +545,7 @@ plip_device_clear(struct device *dev) enable_irq(dev->irq); } -/* PLIP_ERROR --- wait til other end setteled */ +/* PLIP_ERROR --- wait til other end settled */ static int plip_error(struct device *dev) { diff --git a/drivers/scsi/53c7,8xx.c b/drivers/scsi/53c7,8xx.c index 24d679201c56..99a7d360d1de 100644 --- a/drivers/scsi/53c7,8xx.c +++ b/drivers/scsi/53c7,8xx.c @@ -2424,7 +2424,7 @@ static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) { tmp->select[0] = IDENTIFY (0, cmd->lun); #endif patch_dsa_32(tmp->dsa, dsa_msgout, 1, tmp->select); - patch_dsa_32(tmp->dsa, dsa_cmdout, 0, COMMAND_SIZE(cmd->cmnd[0])); + patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len); patch_dsa_32(tmp->dsa, dsa_cmdout, 1, cmd->cmnd); patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? cmd_dataout : hostdata->script + hostdata->E_other_transfer / @@ -3742,10 +3742,6 @@ int NCR53c7xx_reset (Scsi_Cmnd *cmd) { return SCSI_RESET_SNOOZE; } -const char *NCR53c7xx_info (void) { - return("More info here\n"); -} - /* * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and * therefore shares the scsicam_bios_param function. diff --git a/drivers/scsi/53c7,8xx.h b/drivers/scsi/53c7,8xx.h index 7793f99ac228..1eee787993f1 100644 --- a/drivers/scsi/53c7,8xx.h +++ b/drivers/scsi/53c7,8xx.h @@ -50,12 +50,11 @@ #include extern int NCR53c7xx_abort(Scsi_Cmnd *); extern int NCR53c7xx_detect(Scsi_Host_Template *tpnt); -extern const char *NCR53c7xx_info(void); extern int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); extern int NCR53c7xx_reset(Scsi_Cmnd *); -#define NCR53c7xx {NULL, "NCR53c{7,8}xx (rel 3)", NCR53c7xx_detect, \ - NULL, NCR53c7xx_info, \ +#define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 3)", NCR53c7xx_detect, \ + NULL, NULL, \ NULL, NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset,\ NULL, scsicam_bios_param, \ /* can queue */ 1, /* id */ 7, 255 /* old SG_ALL */, \ diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 19d13b3ddea3..f99f5875ec77 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2306,7 +2306,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) { msgout = NOP; break; case PHASE_CMDOUT: - len = COMMAND_SIZE(cmd->cmnd[0]); + len = cmd->cmd_len; data = cmd->cmnd; /* * XXX for performance reasons, on machines with a diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 4107006c5379..7ae1ee4a0b95 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -268,8 +268,6 @@ #define P_BUSFREE 1 #define P_PARITY 2 -static char *aha152x_id = AHA152X_REVID; - static int port_base = 0; static int this_host = 0; static int can_disconnect = 0; @@ -734,14 +732,6 @@ int aha152x_detect(Scsi_Host_Template * tpnt) return 1; } -/* - * return the name of the thing - */ -const char *aha152x_info(void) -{ - return(aha152x_id); -} - /* * Queue a command and setup interrupts for a free bus. */ @@ -1590,14 +1580,14 @@ void aha152x_intr( int irqno ) if(aha152x_debug & debug_cmd) { printk("DFIFOEMP, outsw (%d words), ", - COMMAND_SIZE(current_SC->cmnd[0])>>1); + current_SC->cmd_len >>1 ); disp_ports(); } #endif outsw( DATAPORT, ¤t_SC->cmnd, - COMMAND_SIZE(current_SC->cmnd[0])>>1 ); + current_SC->cmd_len >>1 ); #if defined(DEBUG_CMD) if(aha152x_debug & debug_cmd) @@ -1622,7 +1612,7 @@ void aha152x_intr( int irqno ) #if defined(DEBUG_CMD) || defined(DEBUG_INTR) if(debug_cmd & debug_intr) printk("sent %d/%d command bytes, ", GETSTCNT(), - COMMAND_SIZE(current_SC->cmnd[0])); + current_SC->cmd_len); #endif } diff --git a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h index 09cf73b2ea7d..b8c9ae9bd1b5 100644 --- a/drivers/scsi/aha152x.h +++ b/drivers/scsi/aha152x.h @@ -12,7 +12,6 @@ #include int aha152x_detect(Scsi_Host_Template *); -const char *aha152x_info(void); int aha152x_command(Scsi_Cmnd *); int aha152x_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int aha152x_abort(Scsi_Cmnd *); @@ -27,10 +26,11 @@ int aha152x_biosparam(Disk *, int, int*); /* Initial value of Scsi_Host entry */ #define AHA152X { /* next */ NULL, \ + /* usage_count */ NULL, \ /* name */ AHA152X_REVID, \ /* detect */ aha152x_detect, \ /* release */ NULL, \ - /* info */ aha152x_info, \ + /* info */ NULL, \ /* command */ aha152x_command, \ /* queuecommand */ aha152x_queue, \ /* abort */ aha152x_abort, \ diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 4079522e8116..9011814f609b 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -10,6 +10,8 @@ * have the bios enabled to use the aha1542. * Modified by David Gentzel * Don't call request_dma if dma mask is 0 (for BusLogic BT-445S VL-Bus controller). + * Modified by Matti Aarnio + * Accept parameters from LILO cmd-line. -- 1-Oct-94 */ #include @@ -43,9 +45,38 @@ static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha /* The adaptec can be configured for quite a number of addresses, but I generally do not want the card poking around at random. We allow two addresses - this allows people to use the Adaptec with a Midi -card, which also used 0x330 */ +card, which also used 0x330 -- can be overriden with LILO! */ + +#define MAXBOARDS 2 /* Increase this and the sizes of the + arrays below, if you need more.. */ + +static unsigned int bases[MAXBOARDS]={0x330, 0x334}; + +/* set by aha1542_setup according to the command line */ +static int setup_called[MAXBOARDS] = {0,0}; +static int setup_buson[MAXBOARDS] = {0,0}; +static int setup_busoff[MAXBOARDS] = {0,0}; +static int setup_dmaspeed[MAXBOARDS] = {-1,-1}; + +static char *setup_str[MAXBOARDS] = {(char *)NULL,(char *)NULL}; + +/* + * LILO params: aha1542=[,,[,]] + * + * Where: is any of the valid AHA addresses: + * 0x130, 0x134, 0x230, 0x234, 0x330, 0x334 + * is the time (in microsecs) that AHA spends on the AT-bus + * when transferring data. 1542A power-on default is 11us, + * valid values are in range: 2..15 (decimal) + * is the time that AHA spends OFF THE BUS after while + * it is transferring data (not to monopolize the bus). + * Power-on default is 4us, valid range: 1..64 microseconds. + * Default is jumper selected (1542A: on the J1), + * but experimenter can alter it with this. + * Valid values: 5, 6, 7, 8, 10 (MB/s) + * Factory default is 5 MB/s. + */ -static unsigned int bases[]={0x330, 0x334}; /* The DMA-Controller. We need to fool with this because we want to be able to use the aha1542 without having to have the bios enabled */ @@ -253,6 +284,7 @@ static int aha1542_test_port(int bse, struct Scsi_Host * shpnt) /* In case some other card was probing here, reset interrupts */ aha1542_intr_reset(bse); /* reset interrupts, so they don't block */ + outb(SRST|IRST/*|SCRST*/, CONTROL(bse)); i = jiffies + 2; @@ -302,14 +334,6 @@ static int aha1542_test_port(int bse, struct Scsi_Host * shpnt) return 0; /* 0 = not ok */ } -static const char aha_ident[] = "Adaptec 1542"; - -/* What's this little function for? */ -const char *aha1542_info(void) -{ - return aha_ident; -} - /* A "high" level interrupt handler */ static void aha1542_intr_handle(int foo) { @@ -513,7 +537,7 @@ int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); aha1542_stat(); printk("aha1542_queuecommand: dumping scsi cmd:"); - for (i = 0; i < (COMMAND_SIZE(*cmd)); i++) printk("%02x ", cmd[i]); + for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); printk("\n"); if (*cmd == WRITE_10 || *cmd == WRITE_6) return 0; /* we are still testing, so *don't* write */ @@ -549,7 +573,7 @@ int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) memset(&ccb[mbo], 0, sizeof(struct ccb)); - ccb[mbo].cdblen = COMMAND_SIZE(*cmd); /* SCSI Command Descriptor Block Length */ + ccb[mbo].cdblen = SCpnt->cmd_len; direction = 0; if (*cmd == READ_10 || *cmd == READ_6) @@ -590,7 +614,6 @@ int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) any2scsi(cptr[i].datalen, sgpnt[i].length); }; any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain)); - if(((unsigned int) buff & 0xff000000)) goto baddma; any2scsi(ccb[mbo].dataptr, cptr); #ifdef DEBUG printk("cptr %x: ",cptr); @@ -601,6 +624,7 @@ int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) ccb[mbo].op = 0; /* SCSI Initiator Command */ SCpnt->host_scribble = NULL; any2scsi(ccb[mbo].datalen, bufflen); + if(((unsigned int) buff & 0xff000000)) goto baddma; any2scsi(ccb[mbo].dataptr, buff); }; ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/ @@ -813,6 +837,66 @@ static int aha1542_query(int base_io, int * transl) return 0; } +/* called from init/main.c */ +void aha1542_setup( char *str, int *ints) +{ + char *ahausage = "aha1542: usage: aha1542=[,,[,]]\n"; + static int setup_idx = 0; + int setup_portbase; + + if(setup_idx >= MAXBOARDS) + { + printk("aha1542: aha1542_setup called too many times! Bad LILO params ?\n"); + printk(" Entryline 1: %s\n",setup_str[0]); + printk(" Entryline 2: %s\n",setup_str[1]); + printk(" This line: %s\n",str); + return; + } + if (ints[0] < 1 || ints[0] > 4) + { + printk("aha1542: %s\n", str ); + printk(ahausage); + printk("aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n"); + } + + setup_called[setup_idx]=ints[0]; + setup_str[setup_idx]=str; + + setup_portbase = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */ + setup_buson [setup_idx] = ints[0] >= 2 ? ints[2] : 7; + setup_busoff [setup_idx] = ints[0] >= 3 ? ints[3] : 5; + if (ints[0] >= 4) { + int atbt = -1; + switch (ints[4]) { + case 5: + atbt = 0x00; + break; + case 6: + atbt = 0x04; + break; + case 7: + atbt = 0x01; + break; + case 8: + atbt = 0x02; + break; + case 10: + atbt = 0x03; + break; + default: + printk("aha1542: %s\n", str ); + printk(ahausage); + printk("aha1542: Valid values for DMASPEED are 5-8, 10 MB/s. Using jumper defaults.\n"); + break; + } + setup_dmaspeed[setup_idx] = atbt; + } + + if (setup_portbase != 0) + bases[setup_idx] = setup_portbase; + + ++setup_idx; +} /* return non-zero on detection */ int aha1542_detect(Scsi_Host_Template * tpnt) @@ -826,12 +910,19 @@ int aha1542_detect(Scsi_Host_Template * tpnt) int indx; DEB(printk("aha1542_detect: \n")); - + for(indx = 0; indx < sizeof(bases)/sizeof(bases[0]); indx++) - if(!check_region(bases[indx], 4)) { + if(bases[indx] != 0 && !check_region(bases[indx], 4)) { shpnt = scsi_register(tpnt, sizeof(struct aha1542_hostdata)); + /* For now we do this - until kmalloc is more intelligent + we are resigned to stupid hacks like this */ + if ((unsigned int) shpnt > 0xffffff) { + printk("Invalid address for shpnt with 1542.\n"); + goto unregister; + } + if(!aha1542_test_port(bases[indx], shpnt)) goto unregister; @@ -841,6 +932,12 @@ int aha1542_detect(Scsi_Host_Template * tpnt) { unchar oncmd[] = {CMD_BUSON_TIME, 7}; unchar offcmd[] = {CMD_BUSOFF_TIME, 5}; + + if(setup_called[indx]) + { + oncmd[1] = setup_buson[indx]; + offcmd[1] = setup_busoff[indx]; + } aha1542_intr_reset(base_io); aha1542_out(base_io, oncmd, 2); @@ -848,6 +945,14 @@ int aha1542_detect(Scsi_Host_Template * tpnt) aha1542_intr_reset(base_io); aha1542_out(base_io, offcmd, 2); WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); + if (setup_dmaspeed[indx] >= 0) + { + unchar dmacmd[] = {CMD_DMASPEED, 0}; + dmacmd[1] = setup_dmaspeed[indx]; + aha1542_intr_reset(base_io); + aha1542_out(base_io, dmacmd, 2); + WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); + } while (0) { fail: printk("aha1542_detect: setting bus on/off-time failed\n"); @@ -889,6 +994,7 @@ int aha1542_detect(Scsi_Host_Template * tpnt) } aha_host[irq_level - 9] = shpnt; shpnt->io_port = base_io; + shpnt->n_io_port = 4; /* Number of bytes of I/O space used */ shpnt->dma_channel = dma_chan; shpnt->irq = irq_level; HOSTDATA(shpnt)->bios_translation = trans; @@ -1120,3 +1226,12 @@ int aha1542_biosparam(Scsi_Disk * disk, int dev, int * ip) /* if (ip[2] >= 1024) ip[2] = 1024; */ return 0; } + + +#ifdef MODULE +/* Eventually this will go into an include file, but this will be later */ +Scsi_Host_Template driver_template = AHA1542; + +#include "scsi_module.c" +#endif + diff --git a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h index a41e755e57ff..005a1f1e8814 100644 --- a/drivers/scsi/aha1542.h +++ b/drivers/scsi/aha1542.h @@ -69,6 +69,7 @@ #define CMD_EMBOI 0x05 /* Enable MailBox Out Interrupt */ #define CMD_BUSON_TIME 0x07 /* Set Bus-On Time */ #define CMD_BUSOFF_TIME 0x08 /* Set Bus-Off Time */ +#define CMD_DMASPEED 0x09 /* Set AT Bus Transfer Speed */ #define CMD_RETDEVS 0x0a /* Return Installed Devices */ #define CMD_RETCONF 0x0b /* Return Configuration Data */ #define CMD_RETSETUP 0x0d /* Return Setup Data */ @@ -132,7 +133,6 @@ int aha1542_detect(Scsi_Host_Template *); int aha1542_command(Scsi_Cmnd *); int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int aha1542_abort(Scsi_Cmnd *); -const char *aha1542_info(void); int aha1542_reset(Scsi_Cmnd *); int aha1542_biosparam(Disk *, int, int*); @@ -144,11 +144,11 @@ int aha1542_biosparam(Disk *, int, int*); #define NULL 0 #endif -#define AHA1542 { NULL, \ +#define AHA1542 { NULL, NULL, \ "Adaptec 1542", \ aha1542_detect, \ NULL, \ - aha1542_info, \ + NULL, \ aha1542_command, \ aha1542_queuecommand, \ aha1542_abort, \ diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index 8db54c9be99c..baf310de4860 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -163,12 +163,6 @@ int aha1740_test_port(void) return 0; } -const char *aha1740_info(void) -{ - static char buffer[] = "Adaptec 174x (EISA)"; - return buffer; -} - /* A "high" level interrupt handler */ void aha1740_intr_handle(int foo) { @@ -273,7 +267,7 @@ int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) i = -1; printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); printk("scsi cmd:"); - for (i = 0; i < (COMMAND_SIZE(*cmd)); i++) printk("%02x ", cmd[i]); + for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); printk("\n"); #endif @@ -302,7 +296,7 @@ int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) printk("Sending command (%d %x)...",ecbno, done); #endif - ecb[ecbno].cdblen = COMMAND_SIZE(*cmd); /* SCSI Command Descriptor Block Length */ + ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command Descriptor Block Length */ direction = 0; if (*cmd == READ_10 || *cmd == READ_6) diff --git a/drivers/scsi/aha1740.h b/drivers/scsi/aha1740.h index cb96ee4c18aa..dae31cc1f081 100644 --- a/drivers/scsi/aha1740.h +++ b/drivers/scsi/aha1740.h @@ -156,7 +156,6 @@ int aha1740_detect(Scsi_Host_Template *); int aha1740_command(Scsi_Cmnd *); int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int aha1740_abort(Scsi_Cmnd *); -const char *aha1740_info(void); int aha1740_reset(Scsi_Cmnd *); int aha1740_biosparam(Disk *, int, int*); @@ -167,11 +166,11 @@ int aha1740_biosparam(Disk *, int, int*); #define NULL 0 #endif -#define AHA1740 {NULL, \ - "Adaptec 1740", \ +#define AHA1740 {NULL, NULL, \ + "Adaptec 174x (EISA)", \ aha1740_detect, \ NULL, \ - aha1740_info, \ + NULL, \ aha1740_command, \ aha1740_queuecommand, \ aha1740_abort, \ diff --git a/drivers/scsi/aha274x.c b/drivers/scsi/aha274x.c index 109c4e715534..abadeab39b85 100644 --- a/drivers/scsi/aha274x.c +++ b/drivers/scsi/aha274x.c @@ -1033,11 +1033,11 @@ int aha274x_detect(Scsi_Host_Template *template) found += aha274x_register(template, type, base); } } - template->name = (char *)aha274x_info(); + template->name = (char *)aha274x_info(NULL); return(found); } -const char *aha274x_info(void) +const char *aha274x_info(struct Scsi_Host * shost) { return("Adaptec AHA274x/284x (EISA/VL-bus -> Fast SCSI) " AHA274X_SEQ_VERSION "/" @@ -1100,7 +1100,7 @@ void aha274x_buildscb(struct aha274x_host *p, * little-endian format. */ addr = cmd->cmnd; - scb->SCSI_cmd_length = COMMAND_SIZE(cmd->cmnd[0]); + scb->SCSI_cmd_length = cmd->cmd_len; memcpy(scb->SCSI_cmd_pointer, &addr, sizeof(scb->SCSI_cmd_pointer)); if (cmd->use_sg) { @@ -1155,7 +1155,7 @@ int aha274x_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) #if 0 debug("aha274x_queue: cmd 0x%x (size %u), target %d, lun %d\n", cmd->cmnd[0], - COMMAND_SIZE(cmd->cmnd[0]), + cmd->cmd_len, cmd->target, cmd->lun); #endif diff --git a/drivers/scsi/aha274x.h b/drivers/scsi/aha274x.h index afb9c6578379..b2a1c9e1b2bc 100644 --- a/drivers/scsi/aha274x.h +++ b/drivers/scsi/aha274x.h @@ -32,7 +32,8 @@ */ #define AHA274X { \ NULL, \ - "", \ + NULL, \ + NULL, \ aha274x_detect, \ NULL, \ aha274x_info, \ @@ -57,6 +58,6 @@ extern int aha274x_detect(Scsi_Host_Template *); extern int aha274x_command(Scsi_Cmnd *); extern int aha274x_abort(Scsi_Cmnd *); extern int aha274x_reset(Scsi_Cmnd *); -extern const char *aha274x_info(void); +extern const char *aha274x_info(struct Scsi_Host *); #endif diff --git a/drivers/scsi/buslogic.c b/drivers/scsi/buslogic.c index 068cbde813e6..f3e49c8b9e7a 100644 --- a/drivers/scsi/buslogic.c +++ b/drivers/scsi/buslogic.c @@ -8,17 +8,23 @@ * The original version of this driver was derived from aha1542.[ch] which * is Copyright (C) 1992 Tommy Thorn. Much has been reworked, but most of * basic structure and substantial chunks of code still remain. + * + * Thanks to the following individuals who have made contributions (of + * (code, information, support, or testing) to this driver: + * Eric Youngdale Leonard Zubkoff + * Tomas Hurka Andrew Walker */ /* * TODO: - * 1. Cleanup error handling & reporting. + * 1. Clean up error handling & reporting. * 2. Find out why scatter/gather is limited to 16 requests per command. - * 3. Add multiple outstanding requests. - * 4. See if we can make good use of having more than one command per lun. - * 5. Test/improve/fix abort & reset functions. - * 6. Look at command linking. - * 7. Allow multiple boards to share an IRQ if the bus allows (e.g. EISA). + * 3. Test/improve/fix abort & reset functions. + * 4. Look at command linking. + * 5. Allow multiple boards to share an IRQ if the bus allows (EISA, MCA, + * and PCI). + * 6. Avoid using the 445S workaround for board revs >= D. + * 7. Get cmd_per_lun put in the Scsi_Host structure. */ /* @@ -39,8 +45,6 @@ * BT-542B - ISA first-party DMA with floppy support. * BT-545S - 542B + FAST SCSI and active termination. * BT-545D - 545S + differential termination. - * BT-445S - VESA bus-master FAST SCSI with active termination and floppy - * support. * BT-640A - MCA bus-master with floppy support. * BT-646S - 640A + FAST SCSI and active termination. * BT-646D - 646S + differential termination. @@ -49,14 +53,21 @@ * BT-747D - 747S + differential termination. * BT-757S - 747S + WIDE SCSI. * BT-757D - 747D + WIDE SCSI. + * BT-445S - VESA bus-master FAST SCSI with active termination and floppy + * support. + * BT-445C - 445S + enhanced BIOS & firmware options. * BT-946C - PCI bus-master FAST SCSI. (??? Nothing else known.) * - * Should you require further information on any of these boards, BusLogic - * can be reached at (408)492-9090. + * ??? I believe other boards besides the 445 now have a "C" model, but I + * have no facts on them. * * This driver SHOULD support all of these boards. It has only been tested * with a 747S and 445S. * + * Should you require further information on any of these boards, BusLogic + * can be reached at (408)492-9090. Their BBS # is (408)492-1984 (maybe BBS + * stands for "Big Brother System"?). + * * Places flagged with a triple question-mark are things which are either * unfinished, questionable, or wrong. */ @@ -81,13 +92,27 @@ #include "buslogic.h" #ifndef BUSLOGIC_DEBUG -# define BUSLOGIC_DEBUG UD_ABORT +# define BUSLOGIC_DEBUG 0 #endif -#define BUSLOGIC_VERSION "1.00" +/* If different port addresses are needed (e.g. to install more than two + cards), you must define BUSLOGIC_PORT_OVERRIDE to be a comma-separated list + of the addresses which will be checked. This can also be used to resolve a + conflict if the port-probing at a standard port causes problems with + another board. */ +/* #define BUSLOGIC_PORT_OVERRIDE 0x330, 0x334, 0x130, 0x134, 0x230, 0x234 */ + +/* Define this to be either BIOS_TRANSLATION_DEFAULT or BIOS_TRANSLATION_BIG + if you wish to bypass the test for this, which uses an undocumented port. + The test is believed to fail on at least some AMI BusLogic clones. */ +/* #define BIOS_TRANSLATION_OVERRIDE BIOS_TRANSLATION_BIG */ + +#define BUSLOGIC_VERSION "1.13" /* Not a random value - if this is too large, the system hangs for a long time waiting for something to happen if a board is not installed. */ +/* ??? I don't really like this as it will wait longer on slow machines. + Perhaps we should base this on the loops_per_second "Bogomips" value? */ #define WAITNEXTTIMEOUT 3000000 /* This is for the scsi_malloc call in buslogic_queuecommand. */ @@ -101,22 +126,16 @@ /* Since the SG list is malloced, we have to limit the length. */ #define BUSLOGIC_MAX_SG (BUSLOGIC_SG_MALLOC / sizeof (struct chain)) -/* The DMA-Controller. We need to fool with this because we want to be able to - use an ISA BusLogic without having to have the BIOS enabled. */ -#define DMA_MODE_REG 0xD6 -#define DMA_MASK_REG 0xD4 -#define CASCADE 0xC0 +/* ??? Arbitrary. If we can dynamically allocate the mailbox arrays, I may + bump up this number. */ +#define BUSLOGIC_MAILBOXES 16 -#define BUSLOGIC_MAILBOXES 16 /* ??? Arbitrary? */ +#define BUSLOGIC_NONISA_CMDLUN 4 /* ??? Arbitrary (> 1) */ /* BusLogic boards can be configured for quite a number of port addresses (six to be exact), but I generally do not want the driver poking around at random. We allow two port addresses - this allows people to use a BusLogic - with a MIDI card, which frequently also uses 0x330. If different port - addresses are needed (e.g. to install more than two cards), you must define - BUSLOGIC_PORT_OVERRIDE to be a list of the addresses which will be checked. - This can also be used to resolve a conflict if the port-probing at a - standard port causes problems with another board. */ + with a MIDI card, which frequently also uses 0x330. */ static const unsigned int bases[] = { #ifdef BUSLOGIC_PORT_OVERRIDE BUSLOGIC_PORT_OVERRIDE @@ -129,10 +148,12 @@ static const unsigned int bases[] = { #define BIOS_TRANSLATION_BIG 1 /* Big disk (> 1G) case */ struct hostdata { - unsigned char bus_type; - int bios_translation; /* Mapping bios uses - for compatibility */ + unsigned int bus_type; + unsigned int bios_translation: 1; /* BIOS mapping (for compatibility) */ size_t last_mbi_used; size_t last_mbo_used; + char model[7]; + char firmware_rev[6]; Scsi_Cmnd *sc[BUSLOGIC_MAILBOXES]; struct mailbox mb[2 * BUSLOGIC_MAILBOXES]; struct ccb ccbs[BUSLOGIC_MAILBOXES]; @@ -152,25 +173,28 @@ static int restart(struct Scsi_Host *shpnt); #define CHECK(cond) if (cond) ; else goto fail -#define WAIT(port, mask, allof, noneof) \ - CHECK(wait(port, mask, allof, noneof, WAITNEXTTIMEOUT, FALSE)) -#define WAIT_WHILE(port, mask) WAIT(port, mask, 0, mask) -#define WAIT_UNTIL(port, mask) WAIT(port, mask, mask, 0) -#define WAIT_FAST(port, mask, allof, noneof) \ - CHECK(wait(port, mask, allof, noneof, 100, TRUE)) -#define WAIT_WHILE_FAST(port, mask) WAIT_FAST(port, mask, 0, mask) -#define WAIT_UNTIL_FAST(port, mask) WAIT_FAST(port, mask, mask, 0) +#define WAIT(port, allof, noneof) \ + CHECK(wait(port, allof, noneof, WAITNEXTTIMEOUT, FALSE)) +#define WAIT_WHILE(port, mask) WAIT(port, 0, mask) +#define WAIT_UNTIL(port, mask) WAIT(port, mask, 0) +#define WAIT_FAST(port, allof, noneof) \ + CHECK(wait(port, allof, noneof, 100, TRUE)) +#define WAIT_WHILE_FAST(port, mask) WAIT_FAST(port, 0, mask) +#define WAIT_UNTIL_FAST(port, mask) WAIT_FAST(port, mask, 0) /* If delay != 0, we use the udelay call to regulate the amount of time we - wait. */ -static __inline__ int wait(unsigned short port, unsigned char mask, + wait. + + This is inline as it is always called with constant arguments and hence + will be very well optimized. */ +static __inline__ int wait(unsigned short port, unsigned char allof, unsigned char noneof, unsigned int timeout, int delay) { int bits; for (;;) { - bits = inb(port) & mask; + bits = inb(port); if ((bits & allof) == allof && (bits & noneof) == 0) return TRUE; if (delay) @@ -185,16 +209,12 @@ static void buslogic_prefix(void) printk("BusLogic SCSI: "); } -#if BUSLOGIC_DEBUG static void buslogic_stat(unsigned int base) { int s = inb(STATUS(base)), i = inb(INTERRUPT(base)); - printk("status=%02X intrflags=%02X\n", s, i); + buslogic_printk("status=%02X intrflags=%02X\n", s, i); } -#else -# define buslogic_stat(base) -#endif /* This is a bit complicated, but we need to make sure that an interrupt routine does not send something out while we are in the middle of this. @@ -231,45 +251,60 @@ static int buslogic_out(unsigned int base, const unsigned char *cmdp, } /* Only used at boot time, so we do not need to worry about latency as much - here. */ + here. This waits a very short period of time. We use this if we are not + sure whether the board will respond to the command we just sent. */ static int buslogic_in(unsigned int base, unsigned char *cmdp, size_t len) { cli(); while (len--) { - WAIT_UNTIL(STATUS(base), DIRRDY); + WAIT_UNTIL_FAST(STATUS(base), DIRRDY); *cmdp++ = inb(DATA_IN(base)); } sti(); return FALSE; fail: sti(); +#if (BUSLOGIC_DEBUG & BD_IO) buslogic_printk("buslogic_in failed(%u): ", len + 1); buslogic_stat(base); +#endif return TRUE; } -#if 0 -/* Similar to buslogic_in, except that we wait a very short period of time. - We use this if we know the board is alive and awake, but we are not sure - whether the board will respond the the command we are about to send. */ -static int buslogic_in_fast(unsigned int base, unsigned char *cmdp, size_t len) +static unsigned int makecode(unsigned int haerr, unsigned int scsierr) { - cli(); - while (len--) { - WAIT_UNTIL_FAST(STATUS(base), DIRRDY); - *cmdp++ = inb(DATA_IN(base)); - } - sti(); - return FALSE; - fail: - sti(); - return TRUE; -} + unsigned int hosterr; + const char *errstr = NULL; +#if (BUSLOGIC_DEBUG & BD_ERRORS) && defined(CONFIG_SCSI_CONSTANTS) + static const char *const buslogic_status[] = { + /* 00 */ "Command completed normally", + /* 01-07 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, + /* 08-09 */ NULL, NULL, + /* 0A */ "Linked command completed normally", + /* 0B */ "Linked command completed normally, interrupt generated", + /* 0C-0F */ NULL, NULL, NULL, NULL, + /* 10 */ NULL, + /* 11 */ "Selection timed out", + /* 12 */ "Data overrun/underrun", + /* 13 */ "Unexpected bus free", + /* 14 */ "Target bus phase sequence failure", + /* 15 */ "First byte of outgoing MB was invalid", + /* 16 */ "Invalid CCB Operation Code", + /* 17 */ "Linked CCB does not have the same LUN", + /* 18 */ "Invalid Target Direction received from Host", + /* 19 */ "Duplicate CCB Received in Target Mode", + /* 1A */ "Invalid CCB or Segment List Parameter", + /* 1B */ "Auto request sense failed", + /* 1C */ "SCSI-2 tagged queueing message was rejected by the target", + /* 1D-1F */ NULL, NULL, NULL, + /* 20 */ "Host adapter hardware failure", + /* 21 */ "Target did not respond to SCSI ATN and the HA SCSI bus reset", + /* 22 */ "Host adapter asserted a SCSI bus reset", + /* 23 */ "Other SCSI devices asserted a SCSI bus reset", + }; #endif -static unsigned int makecode(unsigned int hosterr, unsigned int scsierr) -{ - switch (hosterr) { + switch (haerr) { case 0x00: /* Normal completion. */ case 0x0A: /* Linked command complete without error and linked normally. */ @@ -280,7 +315,7 @@ static unsigned int makecode(unsigned int hosterr, unsigned int scsierr) case 0x11: /* Selection time out: the initiator selection or target reselection was not complete within the SCSI - Time out period. */ + time out period. */ hosterr = DID_TIME_OUT; break; @@ -289,6 +324,10 @@ static unsigned int makecode(unsigned int hosterr, unsigned int scsierr) target. The host adapter will generate a SCSI Reset Condition, notifying the host with a RSTS interrupt. */ + case 0x21: /* The target did not respond to SCSI ATN and the host + adapter consequently issued a SCSI bus reset to + clear up the failure. */ + case 0x22: /* The host adapter asserted a SCSI bus reset. */ hosterr = DID_RESET; break; @@ -322,100 +361,38 @@ static unsigned int makecode(unsigned int hosterr, unsigned int scsierr) case 0x1C: /* SCSI-2 tagged queueing message was rejected by the target. */ case 0x20: /* The host adapter hardware failed. */ - case 0x21: /* The target did not respond to SCSI ATN and the host - adapter consequently issued a SCSI bus reset to - clear up the failure. */ - case 0x22: /* The host adapter asserted a SCSI bus reset. */ case 0x23: /* Other SCSI devices asserted a SCSI bus reset. */ -#if BUSLOGIC_DEBUG - buslogic_printk("%X %X\n", hosterr, scsierr); -#endif hosterr = DID_ERROR; /* ??? Couldn't find any better. */ break; default: - buslogic_printk("makecode: unknown hoststatus %X\n", hosterr); +#ifndef CONFIG_SCSI_CONSTANTS + errstr = "unknown hoststatus"; +#endif + hosterr = DID_ERROR; break; } - return (hosterr << 16) | scsierr; -} - -static int test_port(unsigned int base, struct Scsi_Host *shpnt) -{ - unsigned int i; - unsigned char inquiry_cmd[] = { CMD_INQUIRY }; - unsigned char inquiry_result[4]; - unsigned char *cmdp; - int len; - volatile int debug = 0; - - /* Quick and dirty test for presence of the card. */ - if (inb(STATUS(base)) == 0xFF) - return TRUE; - - /* Reset the adapter. I ought to make a hard reset, but it's not really - necessary. */ - -#if BUSLOGIC_DEBUG - buslogic_printk("test_port called\n"); -#endif - - /* In case some other card was probing here, reset interrupts. */ - INTR_RESET(base); /* reset interrupts, so they don't block */ - - outb(RSOFT | RINT/* | RSBUS*/, CONTROL(base)); - - /* Wait a little bit for things to settle down. */ - i = jiffies + 2; - while (i > jiffies); - - debug = 1; - /* Expect INREQ and HARDY, any of the others are bad. */ - WAIT(STATUS(base), STATMASK, INREQ | HARDY, - DACT | DFAIL | CMDINV | DIRRDY | CPRBSY); - - debug = 2; - /* Shouldn't have generated any interrupts during reset. */ - if (inb(INTERRUPT(base)) & INTRMASK) - goto fail; - - /* Perform a host adapter inquiry instead so we do not need to set up the - mailboxes ahead of time. */ - buslogic_out(base, inquiry_cmd, 1); - - debug = 3; - len = 4; - cmdp = &inquiry_result[0]; - while (len--) { - WAIT(STATUS(base), DIRRDY, DIRRDY, 0); - *cmdp++ = inb(DATA_IN(base)); +#if (BUSLOGIC_DEBUG & BD_ERRORS) +# ifdef CONFIG_SCSI_CONSTANTS + if (hosterr != DID_OK) { + if (haerr < ARRAY_SIZE(buslogic_status)) + errstr = buslogic_status[haerr]; + if (errstr == NULL) + errstr = "unknown hoststatus"; } - - debug = 4; - /* Reading port should reset DIRRDY. */ - if (inb(STATUS(base)) & DIRRDY) - goto fail; - - debug = 5; - /* When CMDC, command is completed, and we're though testing. */ - WAIT_UNTIL(INTERRUPT(base), CMDC); - - /* now initialize adapter. */ - - debug = 6; - /* Clear interrupts. */ - outb(RINT, CONTROL(base)); - - debug = 7; - - return FALSE; /* 0 = ok */ - fail: - return TRUE; /* 1 = not ok */ +# else + if (hosterr == DID_ERROR) + errstr = ""; +# endif +#endif + if (errstr != NULL) + buslogic_printk("makecode: %s (%02X)\n", errstr, haerr); + return (hosterr << 16) | scsierr; } const char *buslogic_info(void) { - return "BusLogic SCSI Driver version " BUSLOGIC_VERSION; + return "BusLogic SCSI driver version " BUSLOGIC_VERSION; } /* A "high" level interrupt handler. */ @@ -442,7 +419,7 @@ static void buslogic_interrupt(int junk) ccb = HOSTDATA(shpnt)->ccbs; base = shpnt->io_port; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_INTERRUPT) flag = inb(INTERRUPT(base)); buslogic_printk("buslogic_interrupt: "); @@ -469,15 +446,17 @@ static void buslogic_interrupt(int junk) probably do something special, but for now just printing a message is sufficient. A SCSI reset detected is something that we really need to deal with in some way. */ - if (flag & ~IMBL) { + if (flag & (MBOR | CMDC | RSTS)) { + buslogic_printk("Unusual flag:"); if (flag & MBOR) - printk("MBOR "); + printk(" MBOR"); if (flag & CMDC) - printk("CMDC "); + printk(" CMDC"); if (flag & RSTS) { needs_restart = 1; - printk("RSTS "); + printk(" RSTS"); } + printk("\n"); } INTR_RESET(base); @@ -522,7 +501,7 @@ static void buslogic_interrupt(int junk) return; } -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_INTERRUPT) if (ccb[mbo].tarstat || ccb[mbo].hastat) buslogic_printk("buslogic_interrupt: returning %08X (status %d)\n", ((int)ccb[mbo].hastat << 16) | ccb[mbo].tarstat, @@ -532,7 +511,7 @@ static void buslogic_interrupt(int junk) if (mbistatus == MBX_COMPLETION_NOT_FOUND) continue; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_INTERRUPT) buslogic_printk("...done %u %u\n", mbo, mbi); #endif @@ -540,7 +519,7 @@ static void buslogic_interrupt(int junk) if (!sctmp || !sctmp->scsi_done) { buslogic_printk("buslogic_interrupt: Unexpected interrupt\n"); - buslogic_printk("tarstat=%02X, hastat=%02X id=%d lun=%d ccb#=%d\n", + buslogic_printk("tarstat=%02X, hastat=%02X id=%d lun=%d ccb#=%u\n", ccb[mbo].tarstat, ccb[mbo].hastat, ccb[mbo].id, ccb[mbo].lun, mbo); return; @@ -550,26 +529,17 @@ static void buslogic_interrupt(int junk) if (sctmp->host_scribble) scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC); -#if 0 /* ??? */ - /* Fetch the sense data, and tuck it away, in the required slot. The - BusLogic automatically fetches it, and there is no guarantee that we - will still have it in the cdb when we come back. */ - if (ccb[mbo].tarstat == 2) /* ??? */ - memcpy(sctmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen], - sizeof sctmp->sense_buffer); -#endif - /* ??? more error checking left out here */ - if (mbistatus != MBX_COMPLETION_OK) + if (mbistatus != MBX_COMPLETION_OK) { /* ??? This is surely wrong, but I don't know what's right. */ errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat); - else + } else errstatus = 0; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_INTERRUPT) if (errstatus) - buslogic_printk("error: %08X %04X %04X\n", - errstatus, ccb[mbo].hastat, ccb[mbo].tarstat); + buslogic_printk("error: %04X %04X\n", + ccb[mbo].hastat, ccb[mbo].tarstat); if (status_byte(ccb[mbo].tarstat) == CHECK_CONDITION) { size_t i; @@ -594,6 +564,7 @@ static void buslogic_interrupt(int junk) } } +/* ??? Why does queuecommand return a value? scsi.c never looks at it... */ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) { static const unsigned char buscmd[] = { CMD_START_SCSI }; @@ -607,7 +578,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) struct mailbox *mb; struct ccb *ccb; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_COMMAND) if (target > 1) { scpnt->result = DID_TIME_OUT << 16; done(scpnt); @@ -616,7 +587,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) #endif if (*cmd == REQUEST_SENSE) { -#ifndef DEBUG +#if (BUSLOGIC_DEBUG & (BD_COMMAND | BD_ERRORS)) if (bufflen != sizeof scpnt->sense_buffer) { buslogic_printk("Wrong buffer length supplied for request sense" " (%d)\n", @@ -628,7 +599,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) return 0; } -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_COMMAND) { int i; @@ -671,8 +642,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) mbo = 0; } while (mbo != HOSTDATA(scpnt->host)->last_mbo_used); - if (mb[mbo].status != MBX_NOT_IN_USE - || HOSTDATA(scpnt->host)->sc[mbo]) { + if (mb[mbo].status != MBX_NOT_IN_USE || HOSTDATA(scpnt->host)->sc[mbo]) { /* ??? Instead of panicing, should we enable OMBR interrupts and sleep until we get one? */ panic("buslogic.c: unable to find empty mailbox"); @@ -686,7 +656,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) sti(); -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_COMMAND) buslogic_printk("sending command (%d %08X)...", mbo, done); #endif @@ -731,7 +701,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) } ccb[mbo].datalen = scpnt->use_sg * sizeof (struct chain); ccb[mbo].dataptr = cptr; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_COMMAND) { unsigned char *ptr; @@ -756,7 +726,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) ccb[mbo].linkptr = NULL; ccb[mbo].commlinkid = 0; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_COMMAND) { size_t i; @@ -768,7 +738,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) #endif if (done) { -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_COMMAND) buslogic_printk("buslogic_queuecommand: now waiting for interrupt: "); buslogic_stat(scpnt->host->io_port); #endif @@ -776,7 +746,7 @@ int buslogic_queuecommand(Scsi_Cmnd *scpnt, void (*done)(Scsi_Cmnd *)) mb[mbo].status = MBX_ACTION_START; /* start scsi command */ buslogic_out(scpnt->host->io_port, buscmd, sizeof buscmd); -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_COMMAND) buslogic_stat(scpnt->host->io_port); #endif } else @@ -793,8 +763,8 @@ static void internal_done(Scsi_Cmnd *scpnt) int buslogic_command(Scsi_Cmnd *scpnt) { -#if BUSLOGIC_DEBUG - buslogic_printk("buslogic_command: ..calling buslogic_queuecommand\n"); +#if (BUSLOGIC_DEBUG & BD_COMMAND) + buslogic_printk("buslogic_command: calling buslogic_queuecommand\n"); #endif buslogic_queuecommand(scpnt, internal_done); @@ -824,46 +794,43 @@ static int setup_mailboxes(unsigned int base, struct Scsi_Host *shpnt) } INTR_RESET(base); /* reset interrupts, so they don't block */ - /* If this fails, this must be an Adaptec board */ if (buslogic_out(base, (unsigned char *)&cmd, sizeof cmd)) - goto must_be_adaptec; + goto fail; + WAIT_UNTIL(INTERRUPT(base), CMDC); - /* Wait until host adapter is done messing around, and then check to see - if the command was accepted. If it failed, this must be an Adaptec - board. */ - WAIT_UNTIL(STATUS(base), HARDY); - if (inb(STATUS(base)) & CMDINV) - goto must_be_adaptec; + ok = TRUE; - WAIT_UNTIL(INTERRUPT(base), CMDC); while (0) { fail: buslogic_printk("buslogic_detect: failed setting up mailboxes\n"); } - ok = TRUE; - must_be_adaptec: + INTR_RESET(base); - if (!ok) - printk("- must be Adaptec\n"); /* So that the adaptec detect looks - clean */ - return ok; + + return !ok; } static int getconfig(unsigned int base, unsigned char *irq, unsigned char *dma, unsigned char *id, - unsigned char *bus_type, unsigned short *max_sg) + char *bus_type, unsigned short *max_sg, + const unsigned char **bios) { unsigned char inquiry_cmd[2]; unsigned char inquiry_result[4]; int i; +#if (BUSLOGIC_DEBUG & BD_DETECT) + buslogic_printk("getconfig: called\n"); +#endif + i = inb(STATUS(base)); if (i & DIRRDY) i = inb(DATA_IN(base)); inquiry_cmd[0] = CMD_RETCONF; buslogic_out(base, inquiry_cmd, 1); - buslogic_in(base, inquiry_result, 3); - WAIT_UNTIL(INTERRUPT(base), CMDC); + if (buslogic_in(base, inquiry_result, 3)) + goto fail; + WAIT_UNTIL_FAST(INTERRUPT(base), CMDC); INTR_RESET(base); /* Defer using the DMA value until we know the bus type. */ *dma = inquiry_result[0]; @@ -889,29 +856,27 @@ static int getconfig(unsigned int base, unsigned char *irq, default: buslogic_printk("Unable to determine BusLogic IRQ level." " Disabling board.\n"); - return TRUE; + goto fail; } *id = inquiry_result[2] & 0x7; + /* I expected Adaptec boards to fail on this, but it doesn't happen... */ inquiry_cmd[0] = CMD_INQEXTSETUP; inquiry_cmd[1] = 4; - if (buslogic_out(base, inquiry_cmd, 2) - || buslogic_in(base, inquiry_result, 4)) - return TRUE; - WAIT_UNTIL(INTERRUPT(base), CMDC); + if (buslogic_out(base, inquiry_cmd, 2)) + goto fail; + if (buslogic_in(base, inquiry_result, inquiry_cmd[1])) + goto fail; + WAIT_UNTIL_FAST(INTERRUPT(base), CMDC); + if (inb(STATUS(base)) & CMDINV) + goto fail; INTR_RESET(base); -#ifdef BUSLOGIC_BUS_TYPE_OVERRIDE - *bus_type = BUS_TYPE_OVERRIDE; -#else *bus_type = inquiry_result[0]; -#endif CHECK(*bus_type == 'A' || *bus_type == 'E' || *bus_type == 'M'); -#ifdef BUSLOGIC_BUS_TYPE_OVERRIDE - if (inquiry_result[0] != BUS_TYPE_OVERRIDE) - buslogic_printk("Overriding bus type %c with %c\n", - inquiry_result[0], BUS_TYPE_OVERRIDE); -#endif + + *bios = (const unsigned char *)((unsigned int)inquiry_result[1] << 12); + *max_sg = (inquiry_result[3] << 8) | inquiry_result[2]; /* We only need a DMA channel for ISA boards. Some other types of boards @@ -935,60 +900,182 @@ static int getconfig(unsigned int base, unsigned char *irq, default: buslogic_printk("Unable to determine BusLogic DMA channel." " Disabling board.\n"); - return TRUE; + goto fail; } else *dma = 0; while (0) { fail: +#if (BUSLOGIC_DEBUG & BD_DETECT) buslogic_printk("buslogic_detect: query board settings\n"); +#endif return TRUE; } return FALSE; } -static int get_translation(unsigned int base) +/* Query the board. This acts both as part of the detection sequence and as a + means to get necessary configuration information. */ +static int buslogic_query(unsigned int base, unsigned char *trans, + unsigned char *irq, unsigned char *dma, + unsigned char *id, char *bus_type, + unsigned short *max_sg, const unsigned char **bios, + char *model, char *firmware_rev) { - /* ??? Unlike UltraStor, I see no way of determining whether > 1G mapping - has been enabled. However, it appears that BusLogic uses a mapping - scheme which varies with the disk size when > 1G mapping is enabled. - For disks <= 1G, this mapping is the same regardless of the setting of - > 1G mapping. Therefore, we should be safe in always assuming that > 1G - mapping has been enabled. */ - return BIOS_TRANSLATION_BIG; -} + unsigned char inquiry_cmd[2]; + unsigned char inquiry_result[6]; + unsigned char geo; + unsigned int i; -/* Query the board to find out the model. */ -static int buslogic_query(unsigned int base, int *trans) -{ - static const unsigned char inquiry_cmd[] = { CMD_INQUIRY }; - unsigned char inquiry_result[4]; - int i; +#if (BUSLOGIC_DEBUG & BD_DETECT) + buslogic_printk("buslogic_query: called\n"); +#endif - i = inb(STATUS(base)); - if (i & DIRRDY) - i = inb(DATA_IN(base)); - buslogic_out(base, inquiry_cmd, sizeof inquiry_cmd); - buslogic_in(base, inquiry_result, 4); - WAIT_UNTIL(INTERRUPT(base), CMDC); + /* Quick and dirty test for presence of the card. */ + if (inb(STATUS(base)) == 0xFF) + goto fail; + + /* Check the GEOMETRY port early for quick bailout on Adaptec boards. */ + geo = inb(GEOMETRY(base)); +#if (BUSLOGIC_DEBUG & BD_DETECT) + buslogic_printk("geometry bits: %02X\n", geo); +#endif + /* Here is where we tell the men from the boys (i.e. Adaptec's don't + support the GEOMETRY port, the men do :-) */ + if (geo == 0xFF) + goto fail; + + /* In case some other card was probing here, reset interrupts. */ INTR_RESET(base); -#if 1 /* ??? Temporary */ - buslogic_printk("Inquiry Bytes: %02X %02X %02X %02X\n", - inquiry_result[0], inquiry_result[1], - inquiry_result[2], inquiry_result[3]); + /* Reset the adapter. I ought to make a hard reset, but it's not really + necessary. */ + outb(RSOFT | RINT/* | RSBUS*/, CONTROL(base)); + + /* Wait a little bit for things to settle down. */ + i = jiffies + 2; + while (i > jiffies); + + /* Expect INREQ and HARDY, any of the others are bad. */ + WAIT(STATUS(base), INREQ | HARDY, DACT | DFAIL | CMDINV | DIRRDY | CPRBSY); + + /* Shouldn't have generated any interrupts during reset. */ + if (inb(INTERRUPT(base)) & INTRMASK) + goto fail; + + /* Getting the BusLogic firmware revision level is a bit tricky. We get + the first two digits (d.d) from CMD_INQUIRY and then use two undocumented + commands to get the remaining digit and letter (d.ddl as in 3.31C). */ + + inquiry_cmd[0] = CMD_INQUIRY; + buslogic_out(base, inquiry_cmd, 1); + if (buslogic_in(base, inquiry_result, 4)) + goto fail; + /* Reading port should reset DIRRDY. */ + if (inb(STATUS(base)) & DIRRDY) + goto fail; + WAIT_UNTIL_FAST(INTERRUPT(base), CMDC); + INTR_RESET(base); + firmware_rev[0] = inquiry_result[2]; + firmware_rev[1] = '.'; + firmware_rev[2] = inquiry_result[3]; + firmware_rev[3] = '\0'; +#if 0 + buslogic_printk("Inquiry Bytes: %02X(%c) %02X(%c)\n", + inquiry_result[0], inquiry_result[0], + inquiry_result[1], inquiry_result[1]); #endif + if (getconfig(base, irq, dma, id, bus_type, max_sg, bios)) + goto fail; + + /* Set up defaults */ +#ifdef BIOS_TRANSLATION_OVERRIDE + *trans = BIOS_TRANSLATION_OVERRIDE; +#else + *trans = BIOS_TRANSLATION_DEFAULT; +#endif + model[0] = '\0'; + model[6] = 0; + + /* ??? Begin undocumented command use. + These may not be supported by clones. */ + + do { + /* ??? It appears as though AMI BusLogic clones don't implement this + feature. As an experiment, if we read a 00 we ignore the GEO_GT_1GB + bit and skip all further undocumented commands. */ + if (geo == 0x00) + break; +#ifndef BIOS_TRANSLATION_OVERRIDE + *trans = ((geo & GEO_GT_1GB) + ? BIOS_TRANSLATION_BIG : BIOS_TRANSLATION_DEFAULT); +#endif + + inquiry_cmd[0] = CMD_VER_NO_LAST; + buslogic_out(base, inquiry_cmd, 1); + if (buslogic_in(base, inquiry_result, 1)) + break; + WAIT_UNTIL_FAST(INTERRUPT(base), CMDC); + INTR_RESET(base); + firmware_rev[3] = inquiry_result[0]; + firmware_rev[4] = '\0'; + + inquiry_cmd[0] = CMD_VER_NO_LETTER; + buslogic_out(base, inquiry_cmd, 1); + if (buslogic_in(base, inquiry_result, 1)) + break; + WAIT_UNTIL_FAST(INTERRUPT(base), CMDC); + INTR_RESET(base); + firmware_rev[4] = inquiry_result[0]; + firmware_rev[5] = '\0'; + + /* Use undocumented command to get model number and revision. */ + + inquiry_cmd[0] = CMD_RET_MODEL_NO; + inquiry_cmd[1] = 6; + buslogic_out(base, inquiry_cmd, 2); + if (buslogic_in(base, inquiry_result, inquiry_cmd[1])) + break; + WAIT_UNTIL_FAST(INTERRUPT(base), CMDC); + INTR_RESET(base); + memcpy(model, inquiry_result, 5); + model[5] = '\0'; + model[6] = inquiry_result[5]; + } while (0); + + /* ??? End undocumented command use. */ + + /* bus_type from getconfig doesn't differentiate between EISA/VESA. We + override using the model number here. */ + /* ??? What bus_type gets returned for PCI? */ + switch (*bus_type) { + case 'E': + switch (model[0]) { + case '4': + *bus_type = 'V'; + break; + case '7': + break; + default: + *bus_type = 'X'; + break; + } + break; + default: + break; + } + while (0) { fail: +#if (BUSLOGIC_DEBUG & BD_DETECT) buslogic_printk("buslogic_query: query board settings\n"); +#endif return TRUE; } - *trans = get_translation(base); - return FALSE; } @@ -997,31 +1084,46 @@ int buslogic_detect(Scsi_Host_Template *tpnt) { unsigned char dma; unsigned char irq; - unsigned int base = 0; + unsigned int base; unsigned char id; - unsigned char bus_type; + char bus_type; unsigned short max_sg; - int trans; - struct Scsi_Host *shpnt = NULL; + unsigned char bios_translation; + const unsigned char *bios; + char *model; + char *firmware_rev; + struct Scsi_Host *shpnt; + size_t indx; int count = 0; - int indx; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_DETECT) buslogic_printk("buslogic_detect:\n"); #endif tpnt->can_queue = BUSLOGIC_MAILBOXES; for (indx = 0; indx < ARRAY_SIZE(bases); indx++) - if (!check_region(bases[indx], 3)) { + if (!check_region(bases[indx], 4)) { shpnt = scsi_register(tpnt, sizeof (struct hostdata)); base = bases[indx]; - if (test_port(base, shpnt)) + model = HOSTDATA(shpnt)->model; + firmware_rev = HOSTDATA(shpnt)->firmware_rev; + if (buslogic_query(base, &bios_translation, &irq, &dma, &id, + &bus_type, &max_sg, &bios, model, firmware_rev)) goto unregister; - /* Set the Bus on/off-times as not to ruin floppy performance. */ - { +#if (BUSLOGIC_DEBUG & BD_DETECT) + buslogic_stat(base); +#endif + + if (setup_mailboxes(base, shpnt)) + goto unregister; + + /* Set the Bus on/off-times as not to ruin floppy performance. + CMD_BUSOFF_TIME is a noop for EISA boards (and possibly + others???). */ + if (bus_type != 'E') { /* The default ON/OFF times for BusLogic adapters is 7/4. */ static const unsigned char oncmd[] = { CMD_BUSON_TIME, 7 }; static const unsigned char offcmd[] = { CMD_BUSOFF_TIME, 5 }; @@ -1029,9 +1131,6 @@ int buslogic_detect(Scsi_Host_Template *tpnt) INTR_RESET(base); buslogic_out(base, oncmd, sizeof oncmd); WAIT_UNTIL(INTERRUPT(base), CMDC); - /* CMD_BUSOFF_TIME is a noop for EISA boards, but as there is - no way to to differentiate EISA from VESA we send it - unconditionally. */ INTR_RESET(base); buslogic_out(base, offcmd, sizeof offcmd); WAIT_UNTIL(INTERRUPT(base), CMDC); @@ -1043,33 +1142,32 @@ int buslogic_detect(Scsi_Host_Template *tpnt) INTR_RESET(base); } - if (buslogic_query(base, &trans)) - goto unregister; - - if (getconfig(base, &irq, &dma, &id, &bus_type, &max_sg)) - goto unregister; - -#if BUSLOGIC_DEBUG - buslogic_stat(base); -#endif - /* Here is where we tell the men from the boys (i.e. an Adaptec - will fail in setup_mailboxes, the men will not :-) */ - if (!setup_mailboxes(base, shpnt)) - goto unregister; - - printk("Configuring BusLogic %s HA at port 0x%03X, IRQ %u", - (bus_type == 'A' ? "ISA" - : (bus_type == 'E' ? "EISA/VESA" : "MCA")), - base, irq); + buslogic_printk("Configuring %s HA at port 0x%03X, IRQ %u", + (bus_type == 'A' ? "ISA" + : (bus_type == 'E' ? "EISA" + : (bus_type == 'M' ? "MCA" + : (bus_type == 'P' ? "PCI" + : (bus_type == 'V' ? "VESA" + : (bus_type == 'X' ? "EISA/VESA" + : "Unknown")))))), + base, irq); + if (bios != NULL) + printk(", BIOS 0x%05X", (unsigned int)bios); if (dma != 0) printk(", DMA %u", dma); printk(", ID %u\n", id); + buslogic_printk("Model Number: %s", + (model[0] ? model : "Unknown")); + if (model[0]) + printk(" (revision %d)", model[6]); + printk("\n"); + buslogic_printk("Firmware revision: %s\n", firmware_rev); -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_DETECT) buslogic_stat(base); #endif -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_DETECT) buslogic_printk("buslogic_detect: enable interrupt channel %d\n", irq); #endif @@ -1083,7 +1181,7 @@ int buslogic_detect(Scsi_Host_Template *tpnt) } if (dma) { - if (request_dma(dma,"buslogic")) { + if (request_dma(dma, "buslogic")) { buslogic_printk("Unable to allocate DMA channel for " "BusLogic controller.\n"); free_irq(irq); @@ -1091,36 +1189,63 @@ int buslogic_detect(Scsi_Host_Template *tpnt) goto unregister; } - if (dma >= 5) { - outb((dma - 4) | CASCADE, DMA_MODE_REG); - outb(dma - 4, DMA_MASK_REG); - } + /* The DMA-Controller. We need to fool with this because we + want to be able to use an ISA BusLogic without having to + have the BIOS enabled. */ + set_dma_mode(dma, DMA_MODE_CASCADE); + enable_dma(dma); } host[irq - 9] = shpnt; shpnt->this_id = id; -#ifdef CONFIG_NO_BUGGY_BUSLOGIC /* Only type 'A' (AT/ISA) bus adapters use unchecked DMA. */ shpnt->unchecked_isa_dma = (bus_type == 'A'); +#ifndef CONFIG_NO_BUGGY_BUSLOGIC + /* There is a hardware bug in the BT-445S prior to revision D. + When the BIOS is enabled and you have more than 16MB of memory, + the card mishandles memory transfers over 16MB which (if viewed + as a 24-bit address) overlap with the BIOS address space. For + example if you have the BIOS located at physical address + 0xDC000 and a DMA transfer from the card to RAM starts at + physical address 0x10DC000 then the transfer is messed up. To + be more precise every fourth byte of the transfer is messed up. + (This analysis courtesy of Tomas Hurka, author of the NeXTSTEP + BusLogic driver.) */ + + if (bus_type == 'V' /* 445 */ + && firmware_rev[0] <= '3' /* S */ + && bios != NULL) { /* BIOS enabled */ +#if 0 + /* ??? Once LNZ's forbidden_addr stuff makes it into the higher + level scsi code, we can use this instead. */ + /* Avoid addresses which "mirror" the BIOS for DMA. */ + shpnt->forbidden_addr = bios; + shpnt->forbidden_size = 16 * 1024; #else - /* Bugs in the firmware of the 445S with >16M. This does not seem - to affect Revision E boards with firmware 3.37. */ - shpnt->unchecked_isa_dma = 1; + /* Use double-buffering. */ + shpnt->unchecked_isa_dma = TRUE; #endif + } +#endif + /* Have to keep cmd_per_lun at 1 for ISA machines otherwise lots + of memory gets sucked up for bounce buffers. */ + /* ??? Unfortunately, cmd_per_lun is only in the + Scsi_Host_Template structure, not the Scsi_Host structure. + Therefore, this could cause high memory consumption if a system + has multiple BusLogic adapters which are a mix of ISA and + non-ISA. */ + if (!shpnt->unchecked_isa_dma) + shpnt->hostt->cmd_per_lun = BUSLOGIC_NONISA_CMDLUN; shpnt->sg_tablesize = max_sg; if (shpnt->sg_tablesize > BUSLOGIC_MAX_SG) shpnt->sg_tablesize = BUSLOGIC_MAX_SG; - /* ??? If we can dynamically allocate the mailbox arrays, I'll - probably bump up this number. */ - shpnt->hostt->can_queue = BUSLOGIC_MAILBOXES; - /* No known way to determine BIOS base address, but we don't - care since we don't use it anyway. */ - shpnt->base = NULL; + /* ??? shpnt->base should really be "const unsigned char *"... */ + shpnt->base = (unsigned char *)bios; shpnt->io_port = base; shpnt->dma_channel = dma; shpnt->irq = irq; - HOSTDATA(shpnt)->bios_translation = trans; - if (trans == BIOS_TRANSLATION_BIG) + HOSTDATA(shpnt)->bios_translation = bios_translation; + if (bios_translation == BIOS_TRANSLATION_BIG) buslogic_printk("Using extended bios translation.\n"); HOSTDATA(shpnt)->last_mbi_used = 2 * BUSLOGIC_MAILBOXES - 1; HOSTDATA(shpnt)->last_mbo_used = BUSLOGIC_MAILBOXES - 1; @@ -1134,7 +1259,7 @@ int buslogic_detect(Scsi_Host_Template *tpnt) = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; size_t i; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_DETECT) buslogic_printk("*** READ CAPACITY ***\n"); #endif for (i = 0; i < sizeof buf; i++) @@ -1146,7 +1271,7 @@ int buslogic_detect(Scsi_Host_Template *tpnt) i, *(int *)(buf + 4), *(int *)buf); } -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_DETECT) buslogic_printk("*** NOW RUNNING MY OWN TEST ***\n"); #endif for (i = 0; i < 4; i++) { @@ -1164,7 +1289,7 @@ int buslogic_detect(Scsi_Host_Template *tpnt) } #endif - snarf_region(bases[indx], 3); /* Register the IO ports that + snarf_region(bases[indx], 4); /* Register the IO ports that we use */ count++; continue; @@ -1292,7 +1417,7 @@ int buslogic_reset(Scsi_Cmnd *scpnt) static const unsigned char buscmd[] = { CMD_START_SCSI }; unsigned int i; -#if BUSLOGIC_DEBUG +#if (BUSLOGIC_DEBUG & BD_RESET) buslogic_printk("buslogic_reset\n"); #endif #if 0 @@ -1303,8 +1428,7 @@ int buslogic_reset(Scsi_Cmnd *scpnt) /* First locate the ccb for this command. */ for (i = 0; i < BUSLOGIC_MAILBOXES; i++) if (HOSTDATA(scpnt->host)->sc[i] == scpnt) { - HOSTDATA(scpnt->host)->ccbs[i].op = 0x81; /* ??? BUS DEVICE - RESET */ + HOSTDATA(scpnt->host)->ccbs[i].op = CCB_OP_BUS_RESET; /* Now tell the BusLogic to flush all pending commands for this target. */ @@ -1329,7 +1453,8 @@ int buslogic_reset(Scsi_Cmnd *scpnt) sctmp->result = DID_RESET << 16; if (sctmp->host_scribble) scsi_free(sctmp->host_scribble, BUSLOGIC_SG_MALLOC); - printk("Sending DID_RESET for target %d\n", scpnt->target); + buslogic_printk("Sending DID_RESET for target %d\n", + scpnt->target); sctmp->scsi_done(scpnt); HOSTDATA(scpnt->host)->sc[i] = NULL; @@ -1347,35 +1472,41 @@ int buslogic_reset(Scsi_Cmnd *scpnt) return SCSI_RESET_PUNT; } +/* ??? This is probably not correct for series "C" boards. I believe these + support separate mappings for each disk. We would need to issue a + CMD_READ_FW_LOCAL_RAM command to check for the particular drive being + queried. Note that series "C" boards can be differentiated by having + HOSTDATA(disk->device->host)->firmware_rev[0] >= '4'. */ int buslogic_biosparam(Disk *disk, int dev, int *ip) { - /* ??? This truncates. Should we round up to next MB? */ - unsigned int mb = disk->capacity >> 11; + unsigned int size = disk->capacity; /* ip[0] == heads, ip[1] == sectors, ip[2] == cylinders */ if (HOSTDATA(disk->device->host)->bios_translation == BIOS_TRANSLATION_BIG - && mb > 1024) { - if (mb > 4096) { + && size >= 0x200000) { /* 1GB */ + if (size >= 0x400000) { /* 2GB */ +#if 0 /* ??? Used in earlier kernels, but disagrees with BusLogic info. */ + if (mb >= 0x800000) { /* 4GB */ + ip[0] = 256; + ip[1] = 64; + } else { + ip[0] = 256; + ip[1] = 32; + } +#else ip[0] = 256; ip[1] = 64; - ip[2] = mb >> 3; -/* if (ip[2] > 1024) - ip[2] = 1024; */ - } else if (mb > 2048) { - ip[0] = 256; - ip[1] = 32; - ip[2] = mb >> 2; +#endif } else { ip[0] = 128; ip[1] = 32; - ip[2] = mb >> 1; } } else { ip[0] = 64; ip[1] = 32; - ip[2] = mb; -/* if (ip[2] > 1024) - ip[2] = 1024; */ } + ip[2] = size / (ip[0] * ip[1]); +/* if (ip[2] > 1024) + ip[2] = 1024; */ return 0; } diff --git a/drivers/scsi/buslogic.h b/drivers/scsi/buslogic.h index 585de430779a..04ca8b01c036 100644 --- a/drivers/scsi/buslogic.h +++ b/drivers/scsi/buslogic.h @@ -20,15 +20,14 @@ int buslogic_reset(Scsi_Cmnd *); int buslogic_biosparam(Disk *, int, int *); #define BUSLOGIC_CMDLUN 1 /* Do not set this too high. It sucks - up lots of memory on machines with > 16Mb - because of the huge number of bounce - buffers that need to be allocated. + up lots of memory on ISA machines + with > 16MB because of the huge number of + bounce buffers that need to be allocated. For boards that use non-ISA bus, we can bump this in the board detect routine. - 10/8/94 ERY */ - + 10/8/94 ERY */ -#define BUSLOGIC { NULL, \ +#define BUSLOGIC { NULL, \ "BusLogic", \ buslogic_detect, \ NULL, \ @@ -65,8 +64,11 @@ int buslogic_biosparam(Disk *, int, int *); #define BD_ABORT 0x0001 #define BD_COMMAND 0x0002 #define BD_DETECT 0x0004 -#define BD_INTERRUPT 0x0008 -#define BD_RESET 0x0010 +#define BD_ERRORS 0x0008 +#define BD_INTERRUPT 0x0010 +#define BD_IO 0x0020 +#define BD_RESET 0x0040 +#define BD_UNDOCUMENTED 0x0080 /* I/O Port interface */ /* READ */ @@ -77,18 +79,27 @@ int buslogic_biosparam(Disk *, int, int *); #define HARDY 0x10 /* Host Adapter Ready */ #define CPRBSY 0x08 /* Command/Parameter Register Busy */ #define DIRRDY 0x04 /* Data In Register Ready */ + /* 0x02 is reserved */ #define CMDINV 0x01 /* Command Invalid */ -#define STATMASK 0xFD /* 0x02 is reserved */ #define DATA_IN(base) (STATUS(base) + 1) #define INTERRUPT(base) (STATUS(base) + 2) #define INTV 0x80 /* Interrupt Valid */ + /* 0x70 are reserved */ #define RSTS 0x08 /* SCSI Reset State */ #define CMDC 0x04 /* Command Complete */ #define MBOR 0x02 /* Mailbox Out Ready */ #define IMBL 0x01 /* Incoming Mailbox Loaded */ -#define INTRMASK 0x8F /* 0x70 are reserved */ +#define INTRMASK 0x8F + +/* This undocumented port returns a bitmask indicating geometry translation. */ +#define GEOMETRY(base) (STATUS(base) + 3) +#define GEO_GT_1GB 0x80 /* > 1GB under DOS geometry mapping */ + /* 0x70 are unknown */ +#define GEO_XLATION_S_D1 0x0C /* Disk 1 geometry ("S" models only) */ +#define GEO_XLATION_S_D0 0x03 /* Disk 0 geometry ("S" models only) */ + /* WRITE */ #define CONTROL(base) STATUS(base) @@ -96,6 +107,7 @@ int buslogic_biosparam(Disk *, int, int *); #define RSOFT 0x40 /* Soft Reset */ #define RINT 0x20 /* Interrupt Reset */ #define RSBUS 0x10 /* SCSI Bus Reset */ + /* 0x0F are reserved */ #define COMMAND_PARAMETER(base) (STATUS(base) + 1) #define CMD_TSTCMDCINT 0x00 /* Test CMDC Interrupt */ @@ -120,7 +132,13 @@ int buslogic_biosparam(Disk *, int, int *); #define CMD_HA_DIAG 0x20 /* Host Adapter Diagnostic */ #define CMD_HA_OPTIONS 0x21 /* Host Adapter Options */ #define CMD_INITEXTMB 0x81 /* Initialize Extended Mailbox */ +#define CMD_VER_NO_LAST 0x84 /* Version Number Last Byte (undocumented) */ +#define CMD_VER_NO_LETTER 0x85 /* Version Number One Letter (undocumented) */ +#define CMD_RET_MODEL_NO 0x8B /* Return Model Number (undocumented) */ #define CMD_INQEXTSETUP 0x8D /* Inquire Extended Set-up Information */ +#define CMD_ROUND_ROBIN 0x8F /* Enable strict vs. half-assed round-robin + mailbox filling (undocumented) */ +#define CMD_READ_FW_LCL_RAM 0x91/* Read Firmware Local RAM (undocumented) */ #define CMD_WRITE_INQ_BUF 0x9A /* Write Inquiry Data Buffer (Target Mode Only) */ #define CMD_READ_INQ_BUF 0x9B /* Read Inquiry Data Buffer diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index d7d89d16d4f7..b6976e1bc740 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -367,10 +367,6 @@ int eata_detect (Scsi_Host_Template * tpnt) { return j; } -const char *eata_info (void) { - return driver_name; -} - static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { unsigned int k; struct scatterlist * sgpnt; @@ -471,7 +467,7 @@ int eata_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { cpp->data_len = htonl(SCpnt->request_bufflen); } - memcpy(cpp->cdb, SCpnt->cmnd, COMMAND_SIZE(*SCpnt->cmnd)); + memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); /* Send control packet to the board */ if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) { diff --git a/drivers/scsi/eata.h b/drivers/scsi/eata.h index 164e437da9ab..27b86f3454af 100644 --- a/drivers/scsi/eata.h +++ b/drivers/scsi/eata.h @@ -10,16 +10,16 @@ int eata_detect(Scsi_Host_Template *); int eata_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int eata_abort(Scsi_Cmnd *); -const char *eata_info(void); int eata_reset(Scsi_Cmnd *); int eata_bios_param(Disk *, int, int*); #define EATA { NULL, /* Ptr for modules */ \ + NULL, /* usage count for modules */ \ "EISA EATA 2.0A rev. " EATA_VERSION " by " \ - "Dario_Ballabio@milano.europe.dg.com.",\ + "Dario_Ballabio@milano.europe.dg.com.", \ eata_detect, \ NULL, /* Release */ \ - eata_info, \ + NULL, \ NULL, \ eata_queuecommand, \ eata_abort, \ diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 9caa24ecb83e..6a315918778a 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -375,9 +375,9 @@ struct signature { #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) -static void print_banner( void ) +static void print_banner( struct Scsi_Host * shpnt ) { - printk( "%s", fdomain_16x0_info() ); + printk( "%s", fdomain_16x0_info(shpnt) ); printk( "Future Domain: BIOS version %d.%d, %s\n", bios_major, bios_minor, chip == tmc1800 ? "TMC-1800" @@ -637,7 +637,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) return 0; /* Cannot find valid set of ports */ } - print_banner(); + print_banner(NULL); SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl; FIFO_Data_Count_port = port_base + FIFO_Data_Count; @@ -755,7 +755,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) return 1; } -const char *fdomain_16x0_info(void) +const char *fdomain_16x0_info(struct Scsi_Host * shpnt) { static char buffer[80]; char *pt; @@ -1014,7 +1014,7 @@ void fdomain_16x0_intr( int unused ) if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command - >= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) { + >= current_SC->cmd_len)) { /* We have to get the FIFO direction correct, so I've made a table based on the SCSI Standard of which commands @@ -1376,7 +1376,7 @@ void print_info( Scsi_Cmnd *SCpnt ) unsigned int irr; unsigned int isr; - print_banner(); + print_banner(SCpnt->host); switch (SCpnt->SCp.phase) { case in_arbitration: printk( "arbitration " ); break; case in_selection: printk( "selection " ); break; diff --git a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h index d1ce605e0cd9..f82963d4edbc 100644 --- a/drivers/scsi/fdomain.h +++ b/drivers/scsi/fdomain.h @@ -28,13 +28,13 @@ int fdomain_16x0_detect( Scsi_Host_Template * ); int fdomain_16x0_command( Scsi_Cmnd * ); int fdomain_16x0_abort( Scsi_Cmnd * ); -const char *fdomain_16x0_info( void ); +const char *fdomain_16x0_info( struct Scsi_Host * ); int fdomain_16x0_reset( Scsi_Cmnd * ); int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); int fdomain_16x0_biosparam( Disk *, int, int * ); -#define FDOMAIN_16X0 { NULL, \ - "Future Domain TMC-16x0", \ +#define FDOMAIN_16X0 { NULL, NULL, \ + NULL, \ fdomain_16x0_detect, \ NULL, \ fdomain_16x0_info, \ diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 088537239548..dd6408ed4324 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -35,7 +35,6 @@ #ifndef ASM int generic_NCR5380_abort(Scsi_Cmnd *); int generic_NCR5380_detect(Scsi_Host_Template *); -const char *generic_NCR5380_info(void); int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int generic_NCR5380_reset(Scsi_Cmnd *); @@ -54,8 +53,8 @@ int generic_NCR5380_reset(Scsi_Cmnd *); #ifdef HOSTS_C -#define GENERIC_NCR5380 {NULL, "Trantor T128/T128F/T228", \ - generic_NCR5380_detect, NULL, generic_NCR5380_info, NULL, \ +#define GENERIC_NCR5380 {NULL, NULL, "Trantor T128/T128F/T228", \ + generic_NCR5380_detect, NULL, NULL, NULL, \ generic_NCR5380_queue_command, generic_NCR5380_abort, \ generic_NCR5380_reset, NULL, \ NULL, /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 64c4de82adba..9488c1f1987b 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -227,6 +227,7 @@ 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->host_busy = 0; + retval->block = NULL; if(j > 0xffff) panic("Too many extra bytes requested\n"); retval->extra_bytes = j; retval->loaded_as_module = scsi_loadable_module_flag; diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h index 9eb51d170e39..26b4e1c9fa7d 100644 --- a/drivers/scsi/hosts.h +++ b/drivers/scsi/hosts.h @@ -52,6 +52,9 @@ typedef struct SHT /* Used with loadable modules so we can construct a linked list. */ struct SHT * next; + /* Used with loadable modules so that we know when it is safe to unload */ + int * usage_count; + /* The name pointer is a pointer to the name of the SCSI device detected. @@ -77,14 +80,18 @@ typedef struct SHT int (* detect)(struct SHT *); - /* Used with loadable modules to unload the host structures */ + /* Used with loadable modules to unload the host structures. Note: + there is a default action built into the modules code which may + be sufficient for most host adapters. Thus you may not have to supply + this at all. */ int (*release)(struct Scsi_Host *); /* The info function will return whatever useful - information the developer sees fit. + information the developer sees fit. If not provided, then + the name field will be used instead. */ - const char *(* info)(void); + const char *(* info)(struct Scsi_Host *); /* The command function takes a target, a command (this is a SCSI @@ -221,6 +228,8 @@ typedef struct SHT be two Scsi_Host entries, but only 1 Scsi_Host_Template entries. */ +#define SCSI_HOST_BLOCK 0x800 + struct Scsi_Host { struct Scsi_Host * next; @@ -232,9 +241,15 @@ struct Scsi_Host Scsi_Cmnd *host_queue; Scsi_Host_Template * hostt; + /* Pointer to a circularly linked list - this indicates the hosts + that should be locked out of performing I/O while we have an active + command on this host. */ + struct Scsi_Host * block; + /* These parameters should be set by the detect routine */ unsigned char *base; short unsigned int io_port; + unsigned char n_io_port; unsigned char irq; unsigned char dma_channel; /* diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index deca50baeed8..7d9db4acb347 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -399,7 +399,7 @@ static void in2000_intr_handle(int foo) } /* end while intrpt active */ } -static int in2000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +int in2000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) { unchar direction; unchar *cmd = (unchar *) SCpnt->cmnd; @@ -551,7 +551,7 @@ static void internal_done(Scsi_Cmnd * SCpnt) ++internal_done_flag; } -static int in2000_command(Scsi_Cmnd * SCpnt) +int in2000_command(Scsi_Cmnd * SCpnt) { in2000_queuecommand(SCpnt, internal_done); @@ -560,7 +560,7 @@ static int in2000_command(Scsi_Cmnd * SCpnt) return internal_done_errcode; } -static int in2000_detect(Scsi_Host_Template * tpnt) +int in2000_detect(Scsi_Host_Template * tpnt) { /* Order chosen to reduce conflicts with some multi-port serial boards */ int base_tab[] = { 0x220,0x200,0x110,0x100 }; @@ -632,7 +632,7 @@ static int in2000_detect(Scsi_Host_Template * tpnt) return 1; } -static int in2000_abort(Scsi_Cmnd * SCpnt) +int in2000_abort(Scsi_Cmnd * SCpnt) { DEB(printk("in2000_abort\n")); /* @@ -649,7 +649,7 @@ static inline void delay( unsigned how_long ) while (jiffies < time) ; } -static int in2000_reset(Scsi_Cmnd * SCpnt) +int in2000_reset(Scsi_Cmnd * SCpnt) { DEB(printk("in2000_reset called\n")); /* @@ -671,7 +671,7 @@ static int in2000_reset(Scsi_Cmnd * SCpnt) #endif } -static int in2000_biosparam(Disk * disk, int dev, int* iinfo) +int in2000_biosparam(Disk * disk, int dev, int* iinfo) { int size = disk->capacity; DEB(printk("in2000_biosparam\n")); diff --git a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h index 7a55fb440198..a7564391c736 100644 --- a/drivers/scsi/in2000.h +++ b/drivers/scsi/in2000.h @@ -94,12 +94,12 @@ #define MAX_SENSE 14 #define MAX_STATUS 32 -static int in2000_detect(Scsi_Host_Template *); -static int in2000_command(Scsi_Cmnd *); -static int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int in2000_abort(Scsi_Cmnd *); -static int in2000_reset(Scsi_Cmnd *); -static int in2000_biosparam(Disk *, int, int*); +int in2000_detect(Scsi_Host_Template *); +int in2000_command(Scsi_Cmnd *); +int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int in2000_abort(Scsi_Cmnd *); +int in2000_reset(Scsi_Cmnd *); +int in2000_biosparam(Disk *, int, int*); #ifndef NULL @@ -108,7 +108,7 @@ static int in2000_biosparam(Disk *, int, int*); /* next may be "SG_NONE" or "SG_ALL" or nr. of (1k) blocks per R/W Cmd. */ #define IN2000_SG SG_ALL -#define IN2000 {NULL, "Always IN2000", in2000_detect, NULL, \ +#define IN2000 {NULL, NULL, "Always IN2000", in2000_detect, NULL, \ NULL, in2000_command, \ in2000_queuecommand, \ in2000_abort, \ diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 5dad9529c84f..2ffbdf633734 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -525,17 +525,4 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src return 0; } -/* - * Function : const char *pas16_info(void) - * - * Purpose : provide further information about this driver. - * - * Returns : an empty string. - */ - -const char *pas16_info (void) { - static const char string[]=""; - return string; -} - #include "NCR5380.c" diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index 2dc04026b8d8..b2aede01c28f 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -117,7 +117,6 @@ int pas16_abort(Scsi_Cmnd *); int pas16_biosparam(Disk *, int, int*); int pas16_detect(Scsi_Host_Template *); -const char *pas16_info(void); int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int pas16_reset(Scsi_Cmnd *); @@ -141,8 +140,8 @@ int pas16_reset(Scsi_Cmnd *); #ifdef HOSTS_C -#define MV_PAS16 {NULL, "Pro Audio Spectrum-16 SCSI", \ - pas16_detect, NULL, pas16_info, \ +#define MV_PAS16 {NULL, NULL, "Pro Audio Spectrum-16 SCSI", \ + pas16_detect, NULL, NULL, \ NULL, pas16_queue_command, pas16_abort, pas16_reset, NULL, \ pas16_biosparam, \ /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ diff --git a/drivers/scsi/qlogic.c b/drivers/scsi/qlogic.c index f847393a0c83..826315a6b86b 100644 --- a/drivers/scsi/qlogic.c +++ b/drivers/scsi/qlogic.c @@ -258,7 +258,7 @@ unsigned int i; outb(0x99, qbase + 5); /* timer */ outb(cmd->target, qbase + 4); - for (i = 0; i < COMMAND_SIZE(cmd->cmnd[0]); i++) + for (i = 0; i < cmd->cmd_len; i++) outb(cmd->cmnd[i], qbase + 2); qlcmd = cmd; outb(0x41, qbase + 3); /* select and send command */ @@ -558,7 +558,7 @@ int qlogic_reset(Scsi_Cmnd * cmd) /*----------------------------------------------------------------*/ /* return info string */ -const char *qlogic_info() +const char *qlogic_info(struct Scsi_Host * host) { return qinfo; } diff --git a/drivers/scsi/qlogic.h b/drivers/scsi/qlogic.h index aecb64ff3f0f..eb30cfa9103f 100644 --- a/drivers/scsi/qlogic.h +++ b/drivers/scsi/qlogic.h @@ -2,7 +2,7 @@ #define _QLOGIC_H int qlogic_detect(Scsi_Host_Template * ); -const char * qlogic_info(void); +const char * qlogic_info(struct Scsi_Host *); int qlogic_command(Scsi_Cmnd *); int qlogic_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); int qlogic_abort(Scsi_Cmnd *); @@ -14,6 +14,7 @@ int qlogic_biosparam(Disk *,int,int[]); #endif #define QLOGIC { \ + NULL, \ NULL, \ NULL, \ qlogic_detect, \ diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 46b2b444c56c..96dd21932108 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -269,8 +269,10 @@ static void scan_scsis (struct Scsi_Host * shpnt) SCmd.target = dev; SCmd.lun = lun; + SCmd.request.sem = NULL; /* Used for mutex if loading devices after boot */ SCmd.request.dev = 0xffff; /* Mark not busy */ SCmd.use_sg = 0; + SCmd.cmd_len = 0; SCmd.old_use_sg = 0; SCmd.transfersize = 0; SCmd.underflow = 0; @@ -316,6 +318,7 @@ static void scan_scsis (struct Scsi_Host * shpnt) scsi_cmd[5] = 0; SCmd.request.dev = 0xffff; /* Mark not busy */ + SCmd.cmd_len = 0; scsi_do_cmd (&SCmd, (void *) scsi_cmd, (void *) @@ -462,6 +465,7 @@ static void scan_scsis (struct Scsi_Host * shpnt) scsi_cmd[5] = 0; SCmd.request.dev = 0xffff; /* Mark not busy */ + SCmd.cmd_len = 0; scsi_do_cmd (&SCmd, (void *) scsi_cmd, (void *) @@ -527,10 +531,6 @@ static void scsi_times_out (Scsi_Cmnd * SCpnt) { case NORMAL_TIMEOUT: if (!in_scan_scsis) { - printk("scsi : aborting command due to timeout : pid %lu, scsi%d, id %d, lun %d ", - SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->target, (int) - SCpnt->lun); - print_command (SCpnt->cmnd); #ifdef DEBUG_TIMEOUT scsi_dump_status(); #endif @@ -572,10 +572,10 @@ Scsi_Cmnd * request_queueable (struct request * req, Scsi_Device * device) struct buffer_head * bh, *bhp; if (!device) - panic ("No device passed to allocate_device().\n"); + panic ("No device passed to request_queueable().\n"); if (req && req->dev <= 0) - panic("Invalid device in allocate_device"); + panic("Invalid device in request_queueable"); SCpnt = device->host->host_queue; while(SCpnt){ @@ -629,6 +629,7 @@ Scsi_Cmnd * request_queueable (struct request * req, Scsi_Device * device) SCpnt->old_use_sg = 0; SCpnt->transfersize = 0; SCpnt->underflow = 0; + SCpnt->cmd_len = 0; return SCpnt; } @@ -734,6 +735,7 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device, SCpnt->use_sg = 0; /* Reset the scatter-gather flag */ SCpnt->old_use_sg = 0; SCpnt->transfersize = 0; /* No default transfer size */ + SCpnt->cmd_len = 0; SCpnt->underflow = 0; /* Do not flag underflow conditions */ return SCpnt; } @@ -832,8 +834,10 @@ static void scsi_request_sense (Scsi_Cmnd * SCpnt) SCpnt->request_buffer = &SCpnt->sense_buffer; SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer); SCpnt->use_sg = 0; + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); internal_cmnd (SCpnt); SCpnt->use_sg = SCpnt->old_use_sg; + SCpnt->cmd_len = SCpnt->old_cmd_len; } @@ -891,6 +895,11 @@ void scsi_do_cmd (Scsi_Cmnd * SCpnt, const void *cmnd , (host->host_busy >= host->can_queue)); } else { host->host_busy++; + if (host->block) { + struct Scsi_Host * block; + for(block = host->block; block != host; block = block->block) + block->host_busy |= ~SCSI_HOST_BLOCK; + } sti(); break; }; @@ -924,6 +933,9 @@ void scsi_do_cmd (Scsi_Cmnd * SCpnt, const void *cmnd , SCpnt->request_buffer = buffer; SCpnt->request_bufflen = bufflen; SCpnt->old_use_sg = SCpnt->use_sg; + if (SCpnt->cmd_len == 0) + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); + SCpnt->old_cmd_len = SCpnt->cmd_len; /* Start the timer ticking. */ @@ -1329,6 +1341,7 @@ static void scsi_done (Scsi_Cmnd * SCpnt) SCpnt->request_buffer = SCpnt->buffer; SCpnt->request_bufflen = SCpnt->bufflen; SCpnt->use_sg = SCpnt->old_use_sg; + SCpnt->cmd_len = SCpnt->old_cmd_len; internal_cmnd (SCpnt); }; break; @@ -1337,14 +1350,29 @@ static void scsi_done (Scsi_Cmnd * SCpnt) } if (status == FINISHED) - { - #ifdef DEBUG - printk("Calling done function - at address %08x\n", SCpnt->done); - #endif + { +#ifdef DEBUG + printk("Calling done function - at address %08x\n", SCpnt->done); +#endif host->host_busy--; /* Indicate that we are free */ + if (host->host_busy == 0 && host->block) { + struct Scsi_Host * block; + /* + * Now remove the locks for all of the related hosts. + */ + for(block = host->block; block != host; block = block->block) + block->host_busy &= ~SCSI_HOST_BLOCK; + /* + * Now wake them up. We do this in two separate stages to prevent + * race conditions. + */ + for(block = host->block; block != host; block = block->block) + wake_up(&block->host_wait); + } wake_up(&host->host_wait); SCpnt->result = result | ((exit & 0xff) << 24); SCpnt->use_sg = SCpnt->old_use_sg; + SCpnt->cmd_len = SCpnt->old_cmd_len; SCpnt->done (SCpnt); } @@ -1403,6 +1431,10 @@ int scsi_abort (Scsi_Cmnd * SCpnt, int why) update_timeout(SCpnt, oldto); return 0; } + printk("scsi : aborting command due to timeout : pid %lu, scsi%d, id %d, lun %d ", + SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->target, (int) + SCpnt->lun); + print_command (SCpnt->cmnd); SCpnt->abort_reason = why; switch(host->hostt->abort(SCpnt)) { /* We do not know how to abort. Try waiting another @@ -1787,6 +1819,8 @@ unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end SCpnt->request.dev = -1; /* Mark not busy */ SCpnt->use_sg = 0; SCpnt->old_use_sg = 0; + SCpnt->old_cmd_len = 0; + SCpnt->timeout = 0; SCpnt->underflow = 0; SCpnt->transfersize = 0; SCpnt->host_scribble = NULL; diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index cb0641fb8a5a..9eb8398769c6 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -428,6 +428,8 @@ typedef struct scsi_cmnd { struct Scsi_Host * host; Scsi_Device * device; unsigned char target, lun; + unsigned char cmd_len; + unsigned char old_cmd_len; struct scsi_cmnd *next, *prev; /* These elements define the operation we are about to perform */ diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h index cdaca4006aa4..25fe199ea05d 100644 --- a/drivers/scsi/scsi_debug.h +++ b/drivers/scsi/scsi_debug.h @@ -7,7 +7,6 @@ int scsi_debug_command(Scsi_Cmnd *); int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int scsi_debug_abort(Scsi_Cmnd *); int scsi_debug_biosparam(Disk *, int, int[]); -const char *scsi_debug_info(void); int scsi_debug_reset(Scsi_Cmnd *); #ifndef NULL @@ -16,8 +15,8 @@ int scsi_debug_reset(Scsi_Cmnd *); #define SCSI_DEBUG_MAILBOXES 8 -#define SCSI_DEBUG {NULL, "SCSI DEBUG", scsi_debug_detect, NULL, \ - scsi_debug_info, scsi_debug_command, \ +#define SCSI_DEBUG {NULL, NULL, "SCSI DEBUG", scsi_debug_detect, NULL, \ + NULL, scsi_debug_command, \ scsi_debug_queuecommand, \ scsi_debug_abort, \ scsi_debug_reset, \ diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 05381fb90ae2..c0be923c652b 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -33,12 +33,17 @@ static int ioctl_probe(struct Scsi_Host * host, void *buffer) if ((temp = host->hostt->present) && buffer) { len = get_fs_long ((unsigned long *) buffer); - string = host->hostt->info(); - slen = strlen(string); - if (len > slen) - len = slen + 1; - verify_area(VERIFY_WRITE, buffer, len); - memcpy_tofs (buffer, string, len); + if(host->hostt->info) + string = host->hostt->info(host); + else + string = host->hostt->name; + if(string) { + slen = strlen(string); + if (len > slen) + len = slen + 1; + verify_area(VERIFY_WRITE, buffer, len); + memcpy_tofs (buffer, string, len); + } } return temp; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index ec5cff927995..253f8d2dca03 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -838,6 +838,7 @@ static int sd_init_onedisk(int i) cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0; memset ((void *) &cmd[2], 0, 8); SCpnt->request.dev = 0xffff; /* Mark as really busy again */ + SCpnt->cmd_len = 0; SCpnt->sense_buffer[0] = 0; SCpnt->sense_buffer[2] = 0; @@ -863,6 +864,7 @@ static int sd_init_onedisk(int i) memset ((void *) &cmd[2], 0, 8); cmd[4] = 1; /* Start spin cycle */ SCpnt->request.dev = 0xffff; /* Mark as really busy again */ + SCpnt->cmd_len = 0; SCpnt->sense_buffer[0] = 0; SCpnt->sense_buffer[2] = 0; @@ -897,6 +899,7 @@ static int sd_init_onedisk(int i) memset ((void *) &cmd[2], 0, 8); memset ((void *) buffer, 0, 8); SCpnt->request.dev = 0xffff; /* Mark as really busy again */ + SCpnt->cmd_len = 0; SCpnt->sense_buffer[0] = 0; SCpnt->sense_buffer[2] = 0; diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 9656b01995d4..e35079f76107 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -39,6 +39,7 @@ typedef struct scsi_disk { unsigned char sector_bit_shift; /* power of 2 sectors per FS block */ unsigned ten:1; /* support ten byte read / write */ unsigned remap:1; /* support remapping */ + unsigned has_part_table:1; /* has partition table */ } Scsi_Disk; extern Scsi_Disk * rscsi_disks; diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index 5eb721bb5cd9..0b377911c572 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -362,7 +362,7 @@ int seagate_st0x_detect (Scsi_Host_Template * tpnt) } } -const char *seagate_st0x_info(void) { +const char *seagate_st0x_info(struct Scsi_Host * shpnt) { static char buffer[256]; sprintf(buffer, "scsi%d : %s at irq %d address %p options :" #ifdef ARBITRATE @@ -525,7 +525,7 @@ int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) * Set linked command bit in control field of SCSI command. */ - current_cmnd[COMMAND_SIZE(current_cmnd[0])] |= 0x01; + current_cmnd[SCpnt->cmd_len] |= 0x01; if (linked_connected) { #if (DEBUG & DEBUG_LINKED) printk("scsi%d : using linked commands, current I_T_L nexus is ", diff --git a/drivers/scsi/seagate.h b/drivers/scsi/seagate.h index 5abfd663679b..abc1c930a0a5 100644 --- a/drivers/scsi/seagate.h +++ b/drivers/scsi/seagate.h @@ -17,7 +17,7 @@ int seagate_st0x_command(Scsi_Cmnd *); int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int seagate_st0x_abort(Scsi_Cmnd *); -const char *seagate_st0x_info(void); +const char *seagate_st0x_info(struct Scsi_Host *); int seagate_st0x_reset(Scsi_Cmnd *); #ifndef NULL @@ -26,7 +26,7 @@ int seagate_st0x_reset(Scsi_Cmnd *); int seagate_st0x_biosparam(Disk *, int, int*); -#define SEAGATE_ST0X {NULL, "Seagate ST-01/ST-02", seagate_st0x_detect, \ +#define SEAGATE_ST0X {NULL, NULL, NULL, seagate_st0x_detect, \ NULL, \ seagate_st0x_info, seagate_st0x_command, \ seagate_st0x_queue_command, seagate_st0x_abort, \ diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 936a48b12be8..f60d1ffce1e4 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -220,6 +220,7 @@ static int sg_write(struct inode *inode,struct file *filp,char *buf,int count) int dev=MINOR(inode->i_rdev); Scsi_Cmnd *SCpnt; int bsize,size,amt,i; + unsigned char opcode; unsigned char cmnd[MAX_COMMAND_SIZE]; struct scsi_generic *device=&scsi_generics[dev]; @@ -274,6 +275,9 @@ static int sg_write(struct inode *inode,struct file *filp,char *buf,int count) SCpnt->request.dev=dev; SCpnt->sense_buffer[0]=0; size=COMMAND_SIZE(get_fs_byte(buf)); + size=COMMAND_SIZE(opcode); + if (opcode >= 0xc0 && device->header.twelve_byte) size = 12; + SCpnt->cmd_len = size; memcpy_fromfs(cmnd,buf,size); buf+=size; memcpy_fromfs(device->buff,buf,device->header.pack_len-size-sizeof(struct sg_header)); diff --git a/drivers/scsi/sg.h b/drivers/scsi/sg.h index 76c186ba6898..ea4ae81932b7 100644 --- a/drivers/scsi/sg.h +++ b/drivers/scsi/sg.h @@ -17,7 +17,8 @@ struct sg_header int reply_len; /* maximum length <4096 of expected reply */ int pack_id; /* id number of packet */ int result; /* 0==ok, otherwise refer to errno codes */ - int flags; /* for future use */ + unsigned int twelve_byte:1; /* Force 12 byte command length for group 6 & 7 commands */ + unsigned int other_flags:31; /* for future use */ unsigned char sense_buffer[16]; /* used only by reads */ /* command follows then data for command */ }; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index f8cdab196b61..82dfe55e0fa1 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -325,9 +325,11 @@ static void sr_photocd(struct inode *inode) sec = (unsigned long)buffer[16]/16*10 + (unsigned long)buffer[16]%16; frame = (unsigned long)buffer[17]/16*10 + (unsigned long)buffer[17]%16; sector = min*60*75 + sec*75 + frame; - sector-=CD_BLOCK_OFFSET; if (sector) { - printk("sr_photocd: multisession PhotoCD detected\n"); }} + sector -= CD_BLOCK_OFFSET; + printk("sr_photocd: multisession PhotoCD detected\n"); + } + } scsi_free(buffer,512); SCpnt->request.dev = -1; break; @@ -374,9 +376,11 @@ static void sr_photocd(struct inode *inode) sec = (unsigned long)buffer[2]/16*10 + (unsigned long)buffer[2]%16; frame = (unsigned long)buffer[3]/16*10 + (unsigned long)buffer[3]%16; sector = min*60*75 + sec*75 + frame; - sector-=CD_BLOCK_OFFSET; if (sector) { - printk("sr_photocd: multisession PhotoCD detected: %lu\n",sector); }} + sector -= CD_BLOCK_OFFSET; + printk("sr_photocd: multisession PhotoCD detected: %lu\n",sector); + } + } scsi_free(buffer,512); SCpnt->request.dev = -1; break; @@ -826,10 +830,11 @@ static void sr_init_done (Scsi_Cmnd * SCpnt) static void get_sectorsize(int i){ unsigned char cmd[10]; - unsigned char buffer[513]; + unsigned char *buffer; int the_result, retries; Scsi_Cmnd * SCpnt; + buffer = (unsigned char *) scsi_malloc(512); SCpnt = allocate_device(NULL, scsi_CDs[i].device, 1); retries = 3; @@ -838,6 +843,7 @@ static void get_sectorsize(int i){ cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0; memset ((void *) &cmd[2], 0, 8); SCpnt->request.dev = 0xffff; /* Mark as really busy */ + SCpnt->cmd_len = 0; memset(buffer, 0, 8); @@ -887,6 +893,7 @@ static void get_sectorsize(int i){ scsi_CDs[i].capacity *= 4; scsi_CDs[i].needs_sector_size = 0; }; + scsi_free(buffer, 512); } static void sr_init() diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 5022d9b8fcb5..59a9643e1ab7 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -385,17 +385,4 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src return 0; } -/* - * Function : const char *t128_info(void) - * - * Purpose : provide further information about this driver. - * - * Returns : an empty string. - */ - -const char *t128_info (void) { - static const char string[]=""; - return string; -} - #include "NCR5380.c" diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 59eebae62ebe..fcd4020563fa 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -94,7 +94,6 @@ int t128_abort(Scsi_Cmnd *); int t128_biosparam(Disk *, int, int*); int t128_detect(Scsi_Host_Template *); -const char *t128_info(void); int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int t128_reset(Scsi_Cmnd *); @@ -118,8 +117,8 @@ int t128_reset(Scsi_Cmnd *); #ifdef HOSTS_C -#define TRANTOR_T128 {NULL, "Trantor T128/T128F/T228", t128_detect, NULL, \ - t128_info, \ +#define TRANTOR_T128 {NULL, NULL, "Trantor T128/T128F/T228", t128_detect, NULL, \ + NULL, \ NULL, t128_queue_command, t128_abort, t128_reset, NULL, \ t128_biosparam, \ /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 61d336978166..32cd24ab2c16 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -416,10 +416,6 @@ int u14_34f_detect (Scsi_Host_Template * tpnt) { return j; } -const char *u14_34f_info(void) { - return driver_name; -} - static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { unsigned int k, data_len = 0; struct scatterlist * sgpnt; @@ -506,7 +502,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { cpp->data_len = SCpnt->request_bufflen; } - cpp->scsi_cdbs_len = COMMAND_SIZE(*(unsigned char *)SCpnt->cmnd); + cpp->scsi_cdbs_len = SCpnt->cmd_len; memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len); if (wait_on_busy(sh[j]->io_port)) { diff --git a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h index 9a0b6ebbb243..92d40121bb30 100644 --- a/drivers/scsi/u14-34f.h +++ b/drivers/scsi/u14-34f.h @@ -5,7 +5,6 @@ #define _U14_34F_H int u14_34f_detect(Scsi_Host_Template *); -const char *u14_34f_info(void); int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int u14_34f_abort(Scsi_Cmnd *); int u14_34f_reset(Scsi_Cmnd *); @@ -14,12 +13,13 @@ int u14_34f_biosparam(Disk *, int, int *); #define U14_34F_VERSION "1.10.01" #define ULTRASTOR_14_34F { \ + NULL, \ NULL, \ "UltraStor 14F/34F rev. " U14_34F_VERSION " by " \ "Dario_Ballabio@milano.europe.dg.com.",\ u14_34f_detect, \ NULL, \ - u14_34f_info, \ + NULL, \ NULL, \ u14_34f_queuecommand, \ u14_34f_abort, \ diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index d6d6f898f53a..9d7dca68c821 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -620,7 +620,7 @@ int ultrastor_detect(Scsi_Host_Template * tpnt) return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt); } -const char *ultrastor_info(void) +const char *ultrastor_info(struct Scsi_Host * shpnt) { static char buf[64]; @@ -714,7 +714,7 @@ int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) my_mscp->command_link = 0; /*???*/ my_mscp->scsi_command_link_id = 0; /*???*/ my_mscp->length_of_sense_byte = sizeof SCpnt->sense_buffer; - my_mscp->length_of_scsi_cdbs = COMMAND_SIZE(*(unsigned char *)SCpnt->cmnd); + my_mscp->length_of_scsi_cdbs = SCpnt->cmd_len; memcpy(my_mscp->scsi_cdbs, SCpnt->cmnd, my_mscp->length_of_scsi_cdbs); my_mscp->adapter_status = 0; my_mscp->target_status = 0; diff --git a/drivers/scsi/ultrastor.h b/drivers/scsi/ultrastor.h index 6df818fb19e4..b80a66924620 100644 --- a/drivers/scsi/ultrastor.h +++ b/drivers/scsi/ultrastor.h @@ -14,7 +14,7 @@ #define _ULTRASTOR_H int ultrastor_detect(Scsi_Host_Template *); -const char *ultrastor_info(void); +const char *ultrastor_info(struct Scsi_Host * shpnt); int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int ultrastor_abort(Scsi_Cmnd *); int ultrastor_reset(Scsi_Cmnd *); @@ -29,8 +29,8 @@ int ultrastor_biosparam(Disk *, int, int *); #define ULTRASTOR_24F_PORT 0xC80 -#define ULTRASTOR_14F { NULL, /* Ptr for modules*/ \ - "UltraStor 14F/24F/34F", \ +#define ULTRASTOR_14F { NULL, NULL, /* Ptr for modules*/ \ + NULL, \ ultrastor_detect, \ NULL, /* Release */ \ ultrastor_info, \ diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index b79290a24c9f..c3eed4294d8b 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -900,7 +900,7 @@ int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) register short cdblen; Adapter *host = (Adapter *) SCpnt->host->hostdata; - cdblen = COMMAND_SIZE(cdb[0]); + cdblen = SCpnt->cmd_len; idlun = ((SCpnt->target << 5) & 0xe0) | (SCpnt->lun & 7); SCpnt->scsi_done = done; SCpnt->SCp.phase = 1; @@ -1206,18 +1206,6 @@ int wd7000_reset(Scsi_Cmnd * SCpnt) } -/* - * The info routine in the WD7000 structure isn't per-adapter, so it can't - * really return any useful information about an adapter. Because of this, - * I'm no longer using it to return rev. level. - */ -const char *wd7000_info(void) -{ - static char info[] = "Western Digital WD-7000"; - return info; -} - - /* * This was borrowed directly from aha1542.c, but my disks are organized * this way, so I think it will work OK. Someone who is ambitious can diff --git a/drivers/scsi/wd7000.h b/drivers/scsi/wd7000.h index 8c727d568556..d19cabf2144a 100644 --- a/drivers/scsi/wd7000.h +++ b/drivers/scsi/wd7000.h @@ -16,7 +16,6 @@ int wd7000_detect(Scsi_Host_Template *); int wd7000_command(Scsi_Cmnd *); int wd7000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int wd7000_abort(Scsi_Cmnd *); -const char *wd7000_info(void); int wd7000_reset(Scsi_Cmnd *); int wd7000_biosparam(Disk *, int, int*); @@ -38,11 +37,11 @@ int wd7000_biosparam(Disk *, int, int*); #define WD7000_Q 16 #define WD7000_SG 16 -#define WD7000 { NULL, \ +#define WD7000 { NULL, NULL, \ "Western Digital WD-7000", \ wd7000_detect, \ NULL, \ - wd7000_info, \ + NULL, \ wd7000_command, \ wd7000_queuecommand, \ wd7000_abort, \ diff --git a/fs/locks.c b/fs/locks.c index 2687533644bf..d1de73ad02ad 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -186,7 +186,7 @@ int locks_deadlocked(int my_pid,int blocked_pid) if (ret_val) return -EDEADLOCK; } dlock_wait = dlock_wait->next; - } while (dlock_wait != fl->fl_wait); + } while (dlock_wait != NULL); } return 0; } diff --git a/fs/proc/array.c b/fs/proc/array.c index 65628fd97669..6fd7bccbe6dc 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -12,7 +12,7 @@ * make sure SET_PROCTITLE works. Also removed * bad '!' which forced address recalculation for * EVERY character on the current page. - * + * */ #include diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c index 176d4efa2012..e4d6a9470829 100644 --- a/fs/umsdos/emd.c +++ b/fs/umsdos/emd.c @@ -25,9 +25,10 @@ int umsdos_readdir_kmem( int count) { int ret; + int old_fs = get_fs(); set_fs (KERNEL_DS); ret = msdos_readdir(inode,filp,dirent,count); - set_fs (USER_DS); + set_fs (old_fs); return ret; } /* @@ -39,10 +40,11 @@ int umsdos_file_read_kmem( char *buf, int count) { - int ret; + int ret; + int old_fs = get_fs(); set_fs (KERNEL_DS); ret = msdos_file_read(inode,filp,buf,count); - set_fs (USER_DS); + set_fs (old_fs); return ret; } /* @@ -55,9 +57,10 @@ int umsdos_file_write_kmem( int count) { int ret; + int old_fs = get_fs(); set_fs (KERNEL_DS); ret = msdos_file_write(inode,filp,buf,count); - set_fs (USER_DS); + set_fs (old_fs); return ret; } @@ -208,7 +211,7 @@ int umsdos_writeentry ( return ret; } -#define CHUNK_SIZE (16*UMSDOS_REC_SIZE) +#define CHUNK_SIZE (8*UMSDOS_REC_SIZE) struct find_buffer{ char buffer[CHUNK_SIZE]; int pos; /* read offset in buffer */ diff --git a/include/asm-i386/dma.h b/include/asm-i386/dma.h index 8aa6c70d9355..63540f15942f 100644 --- a/include/asm-i386/dma.h +++ b/include/asm-i386/dma.h @@ -69,6 +69,9 @@ #define MAX_DMA_CHANNELS 8 +/* The maximum address that we can perform a DMA transfer to on this platform */ +#define MAX_DMA_ADDRESS 0xffffff + /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ #define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ diff --git a/include/linux/inet.h b/include/linux/inet.h index d710d8179382..d8511a7ce906 100644 --- a/include/linux/inet.h +++ b/include/linux/inet.h @@ -42,11 +42,14 @@ #ifndef _LINUX_INET_H #define _LINUX_INET_H -#ifdef __i386__ +#if defined(__i386__) #define NET16(x) ((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00)) -#endif -#ifdef __mc680x0__ +#elif defined(__mc68000__) #define NET16(x) (x) +#elif defined(__alpha__) +#define NET16(x) ((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00)) +#else +#error change this to match your machine #endif #ifdef __KERNEL__ diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 1a2512b8eaef..e5923f6ed5a2 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -14,10 +14,12 @@ /* * Call check_region() before probing for your hardware. * Once you have found you hardware, register it with snarf_region(). + * If you unload the driver, use release_region to free ports. */ extern void reserve_setup(char *str, int *ints); extern int check_region(unsigned int from, unsigned int extent); extern void snarf_region(unsigned int from, unsigned int extent); +extern void release_region(unsigned int from, unsigned int extent); #define HAVE_AUTOIRQ diff --git a/include/linux/ip.h b/include/linux/ip.h index f99d1fa7c48d..1d3789638f12 100644 --- a/include/linux/ip.h +++ b/include/linux/ip.h @@ -35,7 +35,7 @@ struct timestamp { #if defined(__i386__) u8 flags:4, overflow:4; -#elif defined(__mc680x0__) +#elif defined(__mc68000__) u8 overflow:4, flags:4; #elif defined(__alpha__) @@ -76,7 +76,7 @@ struct iphdr { #if defined(__i386__) u8 ihl:4, version:4; -#elif defined (__mc680x0__) +#elif defined (__mc68000__) u8 version:4, ihl:4; #elif defined (__alpha__) diff --git a/include/linux/mm.h b/include/linux/mm.h index c2b86997dce0..e2128f033059 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -234,6 +234,11 @@ extern unsigned short * mem_map; #define GFP_NOBUFFER 0x04 #define GFP_NFS 0x05 +/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some + platforms, used as appropriate on others */ + +#define GFP_DMA 0x80 + /* * vm_ops not present page codes for shared memory. * diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 7a9d0576d6f5..4acc22cae1da 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -37,7 +37,7 @@ struct tcphdr { ack:1, urg:1, res2:2; -#elif defined(__mc680x0__) +#elif defined(__mc68000__) u16 res2:2, urg:1, ack:1, diff --git a/init/main.c b/init/main.c index 5c83edcef9f7..ceaabb60ff9b 100644 --- a/init/main.c +++ b/init/main.c @@ -92,6 +92,7 @@ extern void t128_setup(char *str, int *ints); extern void pas16_setup(char *str, int *ints); extern void generic_NCR5380_setup(char *str, int *intr); extern void aha152x_setup(char *str, int *ints); +extern void aha1542_setup(char *str, int *ints); extern void aha274x_setup(char *str, int *ints); extern void scsi_luns_setup(char *str, int *ints); extern void sound_setup(char *str, int *ints); @@ -211,6 +212,9 @@ struct { #ifdef CONFIG_SCSI_AHA152X { "aha152x=", aha152x_setup}, #endif +#ifdef CONFIG_SCSI_AHA1542 + { "aha1542=", aha1542_setup}, +#endif #ifdef CONFIG_SCSI_AHA274X { "aha274x=", aha274x_setup}, #endif diff --git a/kernel/ioport.c b/kernel/ioport.c index 883e58c9c640..c61690e3c71b 100644 --- a/kernel/ioport.c +++ b/kernel/ioport.c @@ -165,6 +165,16 @@ void snarf_region(unsigned int from, unsigned int num) return; } +void release_region(unsigned int from, unsigned int num) +{ + if (from > IO_BITMAP_SIZE*32) + return; + if (from + num > IO_BITMAP_SIZE*32) + num = IO_BITMAP_SIZE*32 - from; + set_bitmap(ioport_registrar, from, num, 0); + return; +} + int check_region(unsigned int from, unsigned int num) { if (from > IO_BITMAP_SIZE*32) diff --git a/modules/NET_MODULES b/modules/NET_MODULES index 0d0b18ba582c..dabb26d0b704 100644 --- a/modules/NET_MODULES +++ b/modules/NET_MODULES @@ -1 +1 @@ -3c509.o de600.o de620.o 3c501.o plip.o 8390.o +3c509.o de600.o de620.o 3c501.o eexpress.o plip.o 8390.o diff --git a/net/inet/proc.c b/net/inet/proc.c index 78f3e7317a0d..c143924bd04b 100644 --- a/net/inet/proc.c +++ b/net/inet/proc.c @@ -17,7 +17,7 @@ * Fixes: * Alan Cox : UDP sockets show the rxqueue/txqueue * using hint flag for the netinfo. - * Pauline Middelink : Pidentd support + * Pauline Middelink : identd support * Alan Cox : Make /proc safer. * Erik Schoenfelder : /proc/net/snmp * Alan Cox : Handle dead sockets properly. diff --git a/net/inet/sock.c b/net/inet/sock.c index 8dd6a36e5a33..fd5f123bd1de 100644 --- a/net/inet/sock.c +++ b/net/inet/sock.c @@ -46,7 +46,7 @@ * Alan Cox : Added RCVBUF,SNDBUF size setting. It suddenly occurred to me how easy it was so... * Rick Sladkey : Relaxed UDP rules for matching packets. * C.E.Hawkins : IFF_PROMISC/SIOCGHWADDR support - * Pauline Middelink : Pidentd support + * Pauline Middelink : identd support * Alan Cox : Fixed connect() taking signals I think. * Alan Cox : SO_LINGER supported * Alan Cox : Error reporting fixes -- 2.39.5