From feb3aa0e8292c283dc08eee5b91c8d4587a8c789 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:09:43 -0500 Subject: [PATCH] Import 1.1.64 --- Makefile | 2 +- arch/i386/config.in | 1 + drivers/block/cdu31a.c | 39 +- drivers/char/keyboard.c | 15 +- drivers/scsi/Makefile | 4 + drivers/scsi/buslogic.c | 1 + drivers/scsi/eata.c | 858 +++++++++++++++++++++++++++++++++++++++ drivers/scsi/eata.h | 37 ++ drivers/scsi/hosts.c | 7 + drivers/scsi/u14-34f.c | 41 +- drivers/scsi/u14-34f.h | 2 +- fs/isofs/inode.c | 4 +- include/linux/resource.h | 2 +- kernel/sys.c | 10 + net/inet/raw.c | 3 +- net/socket.c | 15 +- 16 files changed, 999 insertions(+), 42 deletions(-) create mode 100644 drivers/scsi/eata.c create mode 100644 drivers/scsi/eata.h diff --git a/Makefile b/Makefile index f39abb33f9af..61851b165f58 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 63 +SUBLEVEL = 64 ARCH = i386 diff --git a/arch/i386/config.in b/arch/i386/config.in index 874edf0de92e..e4020af0f98b 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -63,6 +63,7 @@ bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n +bool 'EISA EATA support' CONFIG_SCSI_EATA n #bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n fi diff --git a/drivers/block/cdu31a.c b/drivers/block/cdu31a.c index b9138576b4aa..2f3a259ccaad 100644 --- a/drivers/block/cdu31a.c +++ b/drivers/block/cdu31a.c @@ -11,6 +11,18 @@ * include/linux/cdrom.h). With this interface, CDROMs can be * accessed and standard audio CDs can be played back normally. * + * WARNING - All autoprobes have been removed from the driver. + * You MUST configure the CDU31A via a LILO config + * at boot time or in lilo.conf. I have the + * following in my lilo.conf: + * + * append="cdu31a=0x1f88,0,PAS" + * + * The first number is the I/O base address of the + * card. The second is the interrupt (0 means none). + * The third should be "PAS" if on a Pro-Audio + * spectrum, or nothing if on something else. + * * This interface is (unfortunately) a polled interface. This is * because most Sony interfaces are set up with DMA and interrupts * disables. Some (like mine) do not even have the capability to @@ -73,6 +85,9 @@ * writer doesn't have a multi-session disk, this is all theoritical. * Also, music operation will obviously only work on one session at a * time. + * + * NOTE: At the current time, multi-session still doesn't work. Maybe + * I'll get a multi-session disk soon so I can play with it. * * Raw sector I/O * @@ -195,6 +210,8 @@ static struct 0 means don't use) */ } cdu31a_addresses[] = { +#if 0 /* No autoconfig any more. See Note at beginning + of this file. */ { 0x340, 0 }, /* Standard configuration Sony Interface */ { 0x1f88, 0 }, /* Fusion CD-16 */ { 0x230, 0 }, /* SoundBlaster 16 card */ @@ -203,6 +220,7 @@ static struct { 0x330, 0 }, /* Secondary standard Sony Interface */ { 0x634, 0 }, /* Sound FX SC400 */ { 0x654, 0 }, /* Sound FX SC400 */ +#endif { 0 } }; @@ -253,6 +271,9 @@ static int sony_raw_data_mode = 1; /* 1 if data tracks, 0 if audio. static unsigned int sony_usage = 0; /* How many processes have the drive open. */ +static int sony_pas_init = 0; /* Initialize the Pro-Audio + Spectrum card? */ + static struct s_sony_session_toc *(ses_tocs[MAX_TRACKS]); /* Points to the table of contents. */ @@ -2752,6 +2773,17 @@ cdu31a_setup(char *strings, { irq_used = ints[2]; } + if (*strings != '\0') + { + if (strcmp(strings, "PAS") == 0) + { + sony_pas_init = 1; + } + else + { + printk("CDU31A: Unknown interface type: %s\n", strings[3]); + } + } } static int cdu31a_block_size; @@ -2776,8 +2808,11 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end) * * The following turn on the CD-ROM interface for a Fusion CD-16. */ - outb(0xbc, 0x9a01); - outb(0xe2, 0x9a01); + if (sony_pas_init) + { + outb(0xbc, 0x9a01); + outb(0xe2, 0x9a01); + } drive_found = 0; diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 1372cd8c2a74..eeb0fc4b9093 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -113,6 +113,8 @@ static volatile unsigned char reply_expected = 0; static volatile unsigned char acknowledge = 0; static volatile unsigned char resend = 0; +extern void compute_shiftstate(void); + typedef void (*k_hand)(unsigned char value, char up_flag); typedef void (k_handfn)(unsigned char value, char up_flag); @@ -129,12 +131,12 @@ static k_hand key_handler[16] = { typedef void (*void_fnp)(void); typedef void (void_fn)(void); -static void_fn enter, show_ptregs, send_intr, lastcons, caps_toggle, +static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, SAK, decr_console, incr_console; static void_fnp spec_fn_table[] = { - NULL, enter, show_ptregs, show_mem, + do_null, enter, show_ptregs, show_mem, show_state, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, SAK, @@ -541,7 +543,7 @@ static void keyboard_interrupt(int int_pt_regs) } else { /* maybe beep? */ /* we have at least to update shift_state */ -#if 0 /* how? two almost equivalent choices follow */ +#if 1 /* how? two almost equivalent choices follow */ compute_shiftstate(); #else keysym = U(plain_map[keycode]); @@ -733,14 +735,17 @@ static void do_ignore(unsigned char value, char up_flag) { } +static void do_null() +{ + compute_shiftstate(); +} + static void do_spec(unsigned char value, char up_flag) { if (up_flag) return; if (value >= SIZE(spec_fn_table)) return; - if (!spec_fn_table[value]) - return; spec_fn_table[value](); } diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 92d392d16f6a..6f8765f85fee 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -132,6 +132,10 @@ SCSI_OBJS := $(SCSI_OBJS) ultrastor.o SCSI_SRCS := $(SCSI_SRCS) ultrastor.c endif +ifdef CONFIG_SCSI_EATA +SCSI_OBJS := $(SCSI_OBJS) eata.o +SCSI_SRCS := $(SCSI_SRCS) eata.c +endif scsi.a: $(SCSI_OBJS) diff --git a/drivers/scsi/buslogic.c b/drivers/scsi/buslogic.c index ad4aae1f3cd4..068cbde813e6 100644 --- a/drivers/scsi/buslogic.c +++ b/drivers/scsi/buslogic.c @@ -1010,6 +1010,7 @@ int buslogic_detect(Scsi_Host_Template *tpnt) 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)) { shpnt = scsi_register(tpnt, sizeof (struct hostdata)); diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c new file mode 100644 index 000000000000..eed97a306680 --- /dev/null +++ b/drivers/scsi/eata.c @@ -0,0 +1,858 @@ +/* + * eata.c - Low-level SCSI driver for EISA EATA SCSI controllers. + * + * 14 Nov 1994 rev. 1.07 for linux 1.1.63 Final BETA release. + * 04 Aug 1994 rev. 1.00 for linux 1.1.39 First BETA release. + * + * + * This driver is based on the CAM (Common Access Method Committee) + * EATA (Enhanced AT Bus Attachment) rev. 2.0A. + * + * Released by Dario Ballabio (Dario_Ballabio@milano.europe.dg.com) + * + */ + +/* + * + * This code has been tested with up to 3 Distributed Processing Technology + * PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) eisa controllers, + * no on board cache and no RAID option. + * BIOS must be enabled on the first board and must be disabled for all other + * boards. + * Support is provided for any number of DPT PM2122 eisa boards. + * All boards should be configured at the same IRQ level. + * Multiple IRQ configurations are supported too. + * Boards can be located in any eisa slot (1-15) and are named EATA0, + * EATA1,... in increasing eisa slot number. + * In order to detect the boards, the IRQ must be _level_ triggered + * (not _edge_ triggered). + * + * Other eisa configuration parameters are: + * + * COMMAND QUEUING : ENABLED + * COMMAND TIMEOUT : ENABLED + * CACHE : DISABLED + * + */ + +#include +#include +#include +#include +#include +#include +#include "../block/blk.h" +#include "scsi.h" +#include "hosts.h" +#include "sd.h" +#include +#include "linux/in.h" +#include "eata.h" + +#define NO_DEBUG_DETECT +#define NO_DEBUG_INTERRUPT +#define NO_DEBUG_STATISTICS + +#define MAX_TARGET 8 +#define MAX_IRQ 16 +#define MAX_BOARDS 15 +#define MAX_MAILBOXES 64 +#define MAX_SGLIST 64 +#define MAX_CMD_PER_LUN 2 + +#define FALSE 0 +#define TRUE 1 +#define FREE 0 +#define IN_USE 1 +#define LOCKED 2 +#define IN_RESET 3 +#define NO_IRQ 0xff +#define MAXLOOP 20000 + +#define REG_CMD 7 +#define REG_STATUS 7 +#define REG_AUX_STATUS 8 +#define REG_DATA 0 +#define REG_DATA2 1 +#define REG_SEE 6 +#define REG_LOW 2 +#define REG_LM 3 +#define REG_MID 4 +#define REG_MSB 5 +#define BSY_ASSERTED 0x80 +#define DRQ_ASSERTED 0x08 +#define ABSY_ASSERTED 0x01 +#define IRQ_ASSERTED 0x02 +#define READ_CONFIG_PIO 0xF0 +#define SET_CONFIG_PIO 0xF1 +#define SEND_CP_PIO 0xF2 +#define RECEIVE_SP_PIO 0xF3 +#define TRUNCATE_XFR_PIO 0xF4 +#define RESET_PIO 0xF9 +#define READ_CONFIG_DMA 0xFD +#define SET_CONFIG_DMA 0xFE +#define SEND_CP_DMA 0xFF +#define ASOK 0x00 +#define ASST 0x01 + +/* "EATA", in Big Endian format */ +#define EATA_SIGNATURE 0x41544145 + +/* Board info structure */ +struct eata_info { + ulong data_len; /* Number of valid bytes after this field (30) */ + ulong sign; /* ASCII "EATA" signature */ + unchar :4, /* unused low nibble */ + version:4; /* EATA version */ + unchar ocsena:1, /* Overlap Command Support Enabled */ + tarsup:1, /* Target Mode Supported */ + :2, + dmasup:1, /* DMA Supported */ + drqvld:1, /* DRQ Index (DRQX) is valid */ + ata:1, /* This is an ATA device */ + haaval:1; /* Host Adapter Address Valid */ + ushort cp_pad_len; /* Number of pad bytes after cp_len */ + ulong host_addr; /* Host Adapter SCSI ID */ + ulong cp_len; /* Number of valid bytes in cp */ + ulong sp_len; /* Number of valid bytes in sp */ + ushort queue_size; /* Max number of cp that can be queued */ + ushort unused; + ushort scatt_size; /* Max number of entries in scatter/gather table */ + unchar irq:4, /* Interrupt Request assigned to this controller */ + irq_tr:1, /* 0 for edge triggered, 1 for level triggered */ + second:1, /* 1 if this is a secondary (not primary) controller */ + drqx:2; /* DRQ Index (0=DRQ0, 1=DRQ7, 2=DRQ6, 3=DRQ5) */ + unchar sync; /* 1 if scsi target id 7...0 is running sync scsi */ + ushort ipad[250]; + }; + +/* Board config structure */ +struct eata_config { + ushort len; /* Number of bytes following this field */ + unchar edis:1, /* Disable EATA interface after config command */ + ocena:1, /* Overlapped Commands Enabled */ + mdpena:1, /* Transfer all Modified Data Pointer Messages */ + tarena:1, /* Target Mode Enabled for this controller */ + :4; + unchar cpad[511]; + }; + +/* Returned status packet structure */ +struct mssp { + unchar adapter_status:7, /* State related to current command */ + eoc:1; /* End Of Command (1 = command completed) */ + unchar target_status; /* SCSI status received after data transfer */ + unchar unused[2]; + ulong inv_res_len; /* Number of bytes not transferred */ + Scsi_Cmnd *SCpnt; /* Address set in cp */ + char mess[12]; + }; + +/* Command packet structure */ +struct mscp { + unchar sreset:1, /* SCSI Bus Reset Signal should be asserted */ + interp:1, /* The controller interprets cp, not the target */ + reqsen:1, /* Transfer Request Sense Data to addr using DMA */ + sg:1, /* Use Scatter/Gather */ + :1, + init:1, /* Re-initialize controller and self test */ + dout:1, /* Direction of Transfer is Out (Host to Target) */ + din:1; /* Direction of Transfer is In (Target to Host) */ + unchar sense_len; /* Request Sense Length */ + unchar unused[4]; + unchar phsunit:1, /* Send to Target Physical Unit (bypass RAID) */ + notused:7; + unchar target; /* SCSI Target ID */ + unchar lun:3, /* LUN */ + :2, + luntar:1, /* This cp is for Target (not LUN) */ + dispri:1, /* Disconnect Privilege granted */ + one:1; /* 1 */ + unchar mess[3]; /* Massage to/from Target */ + unchar cdb[12]; /* Command Descriptor Block */ + ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */ + Scsi_Cmnd *SCpnt; /* Address to be returned is sp */ + ulong data_address; /* If sg=0 Data Address, if sg=1 sglist address */ + ulong sp_addr; /* Address where sp is DMA'ed when cp completes */ + ulong sense_addr; /* Address where Sense Data is DMA'ed on error */ + + struct sg_list { + unsigned int address; /* Segment Address */ + unsigned int num_bytes; /* Segment Length */ + } sglist[MAX_SGLIST]; + + unsigned int index; /* cp index */ + }; + +struct hostdata { + struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */ + unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */ + unsigned int last_cp_used; /* Index of last mailbox used */ + unsigned int iocount; /* Total i/o done for this board */ + unsigned int multicount; /* Total ... in second ihdlr loop */ + int board_number; /* Number of this board */ + char board_name[16]; /* Name of this board */ + int in_reset; /* True if board is doing a reset */ + int target_time_out[MAX_TARGET]; /* N. of timeout errors on target */ + int target_reset[MAX_TARGET]; /* If TRUE redo operation on target */ + struct mssp sp[MAX_MAILBOXES]; /* Returned status for this board */ + }; + +static struct Scsi_Host * sh[MAX_BOARDS + 1]; +static char* driver_name = "EATA"; +static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; + +#define HD(board) ((struct hostdata *) &sh[board]->hostdata) +#define BN(board) (HD(board)->board_name) + +static void eata_interrupt_handler(int); +static int do_trace = FALSE; + +static inline unchar wait_on_busy(ushort iobase) { + unsigned int loop = MAXLOOP; + + while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) + if (--loop == 0) return TRUE; + + return FALSE; +} + +static inline unchar do_dma (ushort iobase, unsigned int addr, unchar cmd) { + + if (wait_on_busy(iobase)) return TRUE; + + if (addr) { + outb((char) addr, iobase + REG_LOW); + outb((char) (addr >> 8), iobase + REG_LM); + outb((char) (addr >> 16), iobase + REG_MID); + outb((char) (addr >> 24), iobase + REG_MSB); + } + + outb(cmd, iobase + REG_CMD); + return FALSE; +} + +static inline unchar read_pio (ushort iobase, ushort *start, ushort *end) { + unsigned int loop = MAXLOOP; + ushort *p; + + for (p = start; p <= end; p++) { + + while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) + if (--loop == 0) return TRUE; + + loop = MAXLOOP; + *p = inw(iobase); + } + + return FALSE; +} + +static inline int port_detect (ushort *port_base, unsigned int j, + Scsi_Host_Template * tpnt) { + struct eata_info info; + struct eata_config config; + char name[16]; + + sprintf(name, "%s%d", driver_name, j); + + if (do_dma(*port_base, 0, READ_CONFIG_PIO)) return FALSE; + + /* Read the info structure */ + if (read_pio(*port_base, (ushort *)&info, (ushort *)&info.ipad[0])) + return FALSE; + + /* check the controller "EATA" signature */ + if (info.sign != EATA_SIGNATURE) return FALSE; + + if (!info.haaval || info.ata || info.drqvld || !info.dmasup) { + printk("%s: unusable board found, detaching.\n", name); + return FALSE; + } + + if (!info.irq_tr) { + printk("%s: IRQ must be level triggered, detaching.\n", name); + return FALSE; + } + + /* EATA board detected, allocate its IRQ if not already done */ + if ((info.irq >= MAX_IRQ) || ((irqlist[info.irq] == NO_IRQ) && request_irq + (info.irq, eata_interrupt_handler, SA_INTERRUPT, driver_name))) { + printk("%s: unable to allocate IRQ %u, detaching.\n", name, info.irq); + return FALSE; + } + + /* Set board configuration */ + memset((char *)&config, 0, sizeof(struct eata_config)); + config.len = (ushort) htons((ushort)510); + config.ocena = TRUE; + + if (do_dma(*port_base, (unsigned int)&config, SET_CONFIG_DMA)) { + printk("%s: busy timeout sending configuration, detaching.\n", name); + return FALSE; + } + + sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); + sh[j]->io_port = *port_base; + sh[j]->dma_channel = 0; + sh[j]->irq = info.irq; + sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size); + sh[j]->this_id = (ushort) ntohl(info.host_addr); + sh[j]->can_queue = (ushort) ntohs(info.queue_size); + sh[j]->hostt->cmd_per_lun = MAX_CMD_PER_LUN; + sh[j]->unchecked_isa_dma = FALSE; + memset(HD(j), 0, sizeof(struct hostdata)); + HD(j)->board_number = j; + irqlist[info.irq] = j; + strcpy(BN(j), name); + + if (sh[j]->sg_tablesize > MAX_SGLIST) + sh[j]->sg_tablesize = MAX_SGLIST; + + if (sh[j]->can_queue > MAX_MAILBOXES) + sh[j]->can_queue = MAX_MAILBOXES; + + printk("%s: SCSI ID %d, PORT 0x%03x, IRQ %u, SG %d, "\ + "Mbox %d, CmdLun %d.\n", BN(j), sh[j]->this_id, + sh[j]->io_port, sh[j]->irq, sh[j]->sg_tablesize, + sh[j]->can_queue, sh[j]->hostt->cmd_per_lun); + +#if defined (DEBUG_DETECT) + printk("%s: Version 0x%x, SYNC 0x%x, infol %ld, cpl %ld spl %ld.\n", + name, info.version, info.sync, ntohl(info.data_len), + ntohl(info.cp_len), ntohl(info.sp_len)); +#endif + + return TRUE; +} + +int eata_detect (Scsi_Host_Template * tpnt) { + unsigned int j = 0, k, flags; + + ushort eisa_io_port[] = { + 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88, + 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, 0x0 + }; + + ushort *port_base = eisa_io_port; + + save_flags(flags); + cli(); + + for (k = 0; k < MAX_IRQ; k++) { + irqlist[k] = NO_IRQ; + calls[k] = 0; + } + + for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; + + while (*port_base) { + + if(j < MAX_BOARDS && port_detect(port_base, j, tpnt)) j++; + + port_base++; + } + + restore_flags(flags); + 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; + + sgpnt = (struct scatterlist *) SCpnt->request_buffer; + + for(k = 0; k < SCpnt->use_sg; k++) { + cpp->sglist[k].address = htonl((unsigned int) sgpnt[k].address); + cpp->sglist[k].num_bytes = htonl((unsigned int) sgpnt[k].length); + } + + cpp->data_address = htonl((unsigned int) cpp->sglist); + cpp->data_len = htonl((SCpnt->use_sg * sizeof(struct sg_list))); +} + +int eata_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { + unsigned int i, j, k, flags; + struct mscp *cpp; + struct mssp *spp; + + save_flags(flags); + cli(); + /* j is the board number */ + j = ((struct hostdata *) SCpnt->host->hostdata)->board_number; + + if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid); + + /* i is the mailbox number, look for the first free mailbox + starting from last_cp_used */ + i = HD(j)->last_cp_used + 1; + + for(k = 0; k < sh[j]->can_queue; k++, i++) { + + if (i >= sh[j]->can_queue) i = 0; + + if (HD(j)->cp_stat[i] == FREE) { + HD(j)->last_cp_used = i; + break; + } + } + + if (k == sh[j]->can_queue) { + printk("%s: qcomm, no free mailbox, reseting.\n", BN(j)); + + if (HD(j)->in_reset) + printk("%s: qcomm, already in reset.\n", BN(j)); + else if (eata_reset(SCpnt) == SCSI_RESET_SUCCESS) + panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); + + SCpnt->result = DID_BUS_BUSY << 16; + SCpnt->host_scribble = NULL; + printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); + restore_flags(flags); + done(SCpnt); + return 0; + } + + /* Set pointer to control packet structure */ + cpp = &HD(j)->cp[i]; + + memset(cpp, 0, sizeof(struct mscp)); + + /* Set pointer to status packet structure */ + spp = &HD(j)->sp[i]; + + memset(spp, 0, sizeof(struct mssp)); + + /* The EATA protocol uses Big Endian format, while Intel is Little Endian */ + cpp->sp_addr = htonl((unsigned int) spp); + + SCpnt->scsi_done = done; + cpp->index = i; + SCpnt->host_scribble = (unsigned char *) &cpp->index; + + if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n", + BN(j), i, SCpnt->target, SCpnt->pid); + + if (SCpnt->cmnd[0] == WRITE_10 || SCpnt->cmnd[0] == WRITE_6) + cpp->dout = TRUE; + else + cpp->din = TRUE; + + cpp->reqsen = TRUE; + cpp->dispri = TRUE; + cpp->one = TRUE; + cpp->target = SCpnt->target; + cpp->lun = SCpnt->lun; + cpp->SCpnt = SCpnt; + cpp->sense_addr = htonl((unsigned int) SCpnt->sense_buffer); + cpp->sense_len = sizeof SCpnt->sense_buffer; + + if (SCpnt->use_sg) { + cpp->sg = TRUE; + build_sg_list(cpp, SCpnt); + } + else { + cpp->data_address = htonl((unsigned int) SCpnt->request_buffer); + cpp->data_len = htonl(SCpnt->request_bufflen); + } + + memcpy(cpp->cdb, SCpnt->cmnd, COMMAND_SIZE(*SCpnt->cmnd)); + + /* Send control packet to the board */ + if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) { + SCpnt->result = DID_ERROR << 16; + SCpnt->host_scribble = NULL; + printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n", + BN(j), SCpnt->target, SCpnt->pid); + restore_flags(flags); + done(SCpnt); + return 0; + } + + HD(j)->cp_stat[i] = IN_USE; + restore_flags(flags); + return 0; +} + +int eata_abort (Scsi_Cmnd *SCarg) { + unsigned int i, j, flags; + + save_flags(flags); + cli(); + j = ((struct hostdata *) SCarg->host->hostdata)->board_number; + + if (SCarg->host_scribble == NULL) { + printk("%s: abort, target %d, pid %ld inactive.\n", + BN(j), SCarg->target, SCarg->pid); + return SCSI_ABORT_NOT_RUNNING; + } + + i = *(unsigned int *)SCarg->host_scribble; + printk("%s: abort, mbox %d, target %d, pid %ld.\n", + BN(j), i, SCarg->target, SCarg->pid); + + if (i >= sh[j]->can_queue) + panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); + + if (wait_on_busy(sh[j]->io_port)) { + printk("%s: abort, timeout error.\n", BN(j)); + restore_flags(flags); + return SCSI_ABORT_ERROR; + } + + if (HD(j)->cp_stat[i] == FREE) { + printk("%s: abort, mbox %d is free.\n", BN(j), i); + restore_flags(flags); + return SCSI_ABORT_NOT_RUNNING; + } + + if (HD(j)->cp_stat[i] == IN_USE) { + printk("%s: abort, mbox %d is in use.\n", BN(j), i); + + if (SCarg != HD(j)->cp[i].SCpnt) + panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", + BN(j), i, SCarg, HD(j)->cp[i].SCpnt); + + restore_flags(flags); + return SCSI_ABORT_SNOOZE; + } + + if (HD(j)->cp_stat[i] == IN_RESET) { + printk("%s: abort, mbox %d is in reset.\n", BN(j), i); + restore_flags(flags); + return SCSI_ABORT_ERROR; + } + + if (HD(j)->cp_stat[i] == LOCKED) { + printk("%s: abort, mbox %d is locked.\n", BN(j), i); + restore_flags(flags); + return SCSI_ABORT_NOT_RUNNING; + } + else + panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); +} + +int eata_reset (Scsi_Cmnd *SCarg) { + unsigned int i, j, flags, time, k, limit = 0; + int arg_done = FALSE; + Scsi_Cmnd *SCpnt; + + save_flags(flags); + cli(); + j = ((struct hostdata *) SCarg->host->hostdata)->board_number; + printk("%s: reset, enter, target %d, pid %ld.\n", + BN(j), SCarg->target, SCarg->pid); + + if (SCarg->host_scribble == NULL) + printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); + + if (HD(j)->in_reset) { + printk("%s: reset, exit, already in reset.\n", BN(j)); + restore_flags(flags); + return SCSI_RESET_ERROR; + } + + if (wait_on_busy(sh[j]->io_port)) { + printk("%s: reset, exit, timeout error.\n", BN(j)); + restore_flags(flags); + return SCSI_RESET_ERROR; + } + + for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE; + + for (i = 0; i < sh[j]->can_queue; i++) { + + if (HD(j)->cp_stat[i] == FREE) continue; + + if (HD(j)->cp_stat[i] == LOCKED) { + HD(j)->cp_stat[i] = FREE; + printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); + continue; + } + + SCpnt = HD(j)->cp[i].SCpnt; + HD(j)->cp_stat[i] = IN_RESET; + printk("%s: reset, mbox %d in reset, pid %ld.\n", + BN(j), i, SCpnt->pid); + + if (SCpnt == NULL) + panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); + + if (SCpnt->host_scribble == NULL) + panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); + + if (*(unsigned int *)SCpnt->host_scribble != i) + panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); + + if (SCpnt->scsi_done == NULL) + panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); + + if (SCpnt == SCarg) arg_done = TRUE; + } + + if (do_dma(sh[j]->io_port, 0, RESET_PIO)) { + printk("%s: reset, cannot reset, timeout error.\n", BN(j)); + restore_flags(flags); + return SCSI_RESET_ERROR; + } + + printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); + do_trace = TRUE; + HD(j)->in_reset = TRUE; + sti(); + time = jiffies; + while (jiffies < (time + 200) && limit++ < 100000000) sti(); + cli(); + printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); + + for (i = 0; i < sh[j]->can_queue; i++) { + + /* Skip mailboxes already set free by interrupt */ + if (HD(j)->cp_stat[i] != IN_RESET) continue; + + SCpnt = HD(j)->cp[i].SCpnt; + SCpnt->result = DID_RESET << 16; + SCpnt->host_scribble = NULL; + + /* This mailbox is still waiting for its interrupt */ + HD(j)->cp_stat[i] = LOCKED; + + printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", + BN(j), i, SCpnt->pid); + restore_flags(flags); + SCpnt->scsi_done(SCpnt); + cli(); + } + + HD(j)->in_reset = FALSE; + do_trace = FALSE; + restore_flags(flags); + + if (arg_done) { + printk("%s: reset, exit, success.\n", BN(j)); + return SCSI_RESET_SUCCESS; + } + else { + printk("%s: reset, exit, wakeup.\n", BN(j)); + return SCSI_RESET_PUNT; + } +} + +int eata_bios_param (Disk * disk, int dev, int *ip) { + int size = disk->capacity; + + if(size < 0x200000) { /* < 1Gbyte */ + ip[0]=64; + ip[1]=32; + } + else if (size < 0x400000) { /* < 2Gbyte */ + ip[0]=65; + ip[1]=63; + } + else if(size < 0x800000) { /* < 4Gbyte */ + ip[0]=128; + ip[1]=63; + } + else { /* ok up to 8Gbyte */ + ip[0]=255; + ip[1]=63; + } + + ip[2] = size / (ip[0] * ip[1]); + return 0; +} + +static void eata_interrupt_handler(int irq) { + Scsi_Cmnd *SCpnt; + unsigned int i, j, k, flags, status, loops, total_loops = 0; + struct mssp *spp; + struct mscp *cpp; + + save_flags(flags); + cli(); + + if (irqlist[irq] == NO_IRQ) { + printk("%s, ihdlr, irq %d, unexpected interrupt.\n", driver_name, irq); + restore_flags(flags); + return; + } + + if (do_trace) printk("%s: ihdlr, enter, irq %d, calls %d.\n", + driver_name, irq, calls[irq]); + + /* Service all the boards configured on this irq */ + for (j = 0; sh[j] != NULL; j++) { + + if (sh[j]->irq != irq) continue; + + loops = 0; + + /* Loop until all interrupts for a board are serviced */ + while (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) { + total_loops++; + loops++; + + if (do_trace) printk("%s: ihdlr, start service, count %d.\n", + BN(j), HD(j)->iocount); + + /* Read the status register to clear the interrupt indication */ + inb(sh[j]->io_port + REG_STATUS); + + /* Service all mailboxes of this board */ + for(i = 0; i < sh[j]->can_queue; i++) { + spp = &HD(j)->sp[i]; + + /* Check if this mailbox has completed the operation */ + if (spp->eoc == FALSE) continue; + + spp->eoc = FALSE; + + if (HD(j)->cp_stat[i] == LOCKED) { + HD(j)->cp_stat[i] = FREE; + printk("%s: ihdlr, mbox %d unlocked, count %d.\n", + BN(j), i, HD(j)->iocount); + continue; + } + else if (HD(j)->cp_stat[i] == FREE) { + printk("%s: ihdlr, mbox %d is free, count %d.\n", + BN(j), i, HD(j)->iocount); + continue; + } + else if (HD(j)->cp_stat[i] == IN_RESET) + printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); + else if (HD(j)->cp_stat[i] != IN_USE) + panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i); + + HD(j)->cp_stat[i] = FREE; + cpp = &HD(j)->cp[i]; + SCpnt = spp->SCpnt; + + if (SCpnt == NULL) + panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); + + if (SCpnt != cpp->SCpnt) + panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", + BN(j), i, SCpnt, cpp->SCpnt); + + if (SCpnt->host_scribble == NULL) + panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", + BN(j), i, SCpnt->pid, SCpnt); + + if (*(unsigned int *)SCpnt->host_scribble != i) + panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d,"\ + " irq %d.\n", BN(j), i, SCpnt->pid, + *(unsigned int *)SCpnt->host_scribble, irq); + + switch (spp->adapter_status) { + case ASOK: /* status OK */ + + /* Fix a "READ CAPACITY failed" error on some disk drives */ + if (spp->target_status == INTERMEDIATE_GOOD + && SCpnt->device->type != TYPE_TAPE) + status = DID_ERROR << 16; + + /* If there was a bus reset, redo operation on each target */ + else if (spp->target_status == CONDITION_GOOD + && SCpnt->device->type != TYPE_TAPE + && HD(j)->target_reset[SCpnt->target]) + status = DID_BUS_BUSY << 16; + else + status = DID_OK << 16; + + if (spp->target_status == 0) + HD(j)->target_reset[SCpnt->target] = FALSE; + + HD(j)->target_time_out[SCpnt->target] = 0; + + break; + case ASST: /* Selection Time Out */ + case 0x02: /* Command Time Out */ + + if (HD(j)->target_time_out[SCpnt->target] > 1) + status = DID_ERROR << 16; + else { + status = DID_TIME_OUT << 16; + HD(j)->target_time_out[SCpnt->target]++; + } + + break; + case 0x03: /* SCSI Bus Reset Received */ + + if (SCpnt->device->type != TYPE_TAPE) + status = DID_BUS_BUSY << 16; + else + status = DID_ERROR << 16; + + for (k = 0; k < MAX_TARGET; k++) + HD(j)->target_reset[k] = TRUE; + + break; + case 0x07: /* Bus Parity Error */ + case 0x0c: /* Controller Ram Parity */ + case 0x04: /* Initial Controller Power-up */ + case 0x05: /* Unexpected Bus Phase */ + case 0x06: /* Unexpected Bus Free */ + case 0x08: /* SCSI Hung */ + case 0x09: /* Unexpected Message Reject */ + case 0x0a: /* SCSI Bus Reset Stuck */ + case 0x0b: /* Auto Request-Sense Failed */ + default: + status = DID_ERROR << 16; + break; + } + + SCpnt->result = status | spp->target_status; + HD(j)->iocount++; + + if (loops > 1) HD(j)->multicount++; + +#if defined (DEBUG_INTERRUPT) + if (SCpnt->result || do_trace) +#else + if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || + (spp->adapter_status != ASOK && + spp->adapter_status != ASST && HD(j)->iocount <= 1000) || + do_trace) +#endif + printk("%s: ihdlr, mbox %d, err 0x%x:%x,"\ + " target %d:%d, pid %ld, count %d.\n", + BN(j), i, spp->adapter_status, spp->target_status, + SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount); + + /* Set the command state to inactive */ + SCpnt->host_scribble = NULL; + + restore_flags(flags); + SCpnt->scsi_done(SCpnt); + cli(); + + } /* Mailbox loop */ + + } /* Multiple command loop */ + + } /* Boards loop */ + + calls[irq]++; + + if (total_loops == 0) + printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", + driver_name, irq, calls[irq]); + + if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", + driver_name, irq, calls[irq]); + +#if defined (DEBUG_STATISTICS) + if ((calls[irq] % 100000) == 10000) + for (j = 0; sh[j] != NULL; j++) + printk("%s: ihdlr, calls %d, count %d, multi %d.\n", BN(j), + calls[(sh[j]->irq)], HD(j)->iocount, HD(j)->multicount); +#endif + + restore_flags(flags); + return; +} diff --git a/drivers/scsi/eata.h b/drivers/scsi/eata.h new file mode 100644 index 000000000000..4c5ba2bdbd5e --- /dev/null +++ b/drivers/scsi/eata.h @@ -0,0 +1,37 @@ +/* + * eata.h - used by low-level scsi driver for EISA EATA controllers. + * + */ +#ifndef _EISA_EATA_H +#define _EISA_EATA_H + +#define EATA_VERSION "1.07.00" + +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 */ \ + "EISA EATA 2.0A rev. " EATA_VERSION " by " \ + "Dario_Ballabio@milano.europe.dg.com.",\ + eata_detect, \ + NULL, /* Release */ \ + eata_info, \ + NULL, \ + eata_queuecommand, \ + eata_abort, \ + eata_reset, \ + NULL, \ + eata_bios_param, \ + 0, /* can_queue, reset by detect */ \ + 7, /* this_id, reset by detect */ \ + 0, /* sg_tablesize, reset by detect */ \ + 0, /* cmd_per_lun, reset by detect */ \ + 0, /* number of boards present */ \ + 0, /* unchecked isa dma */ \ + ENABLE_CLUSTERING \ + } +#endif diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 55f22a481d75..93c9d07dc103 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -87,6 +87,10 @@ #include "wd7000.h" #endif +#ifdef CONFIG_SCSI_EATA +#include "eata.h" +#endif + #ifdef CONFIG_SCSI_DEBUG #include "scsi_debug.h" #endif @@ -170,6 +174,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] = #ifdef CONFIG_SCSI_7000FASST WD7000, #endif +#ifdef CONFIG_SCSI_EATA + EATA, +#endif #ifdef CONFIG_SCSI_DEBUG SCSI_DEBUG, #endif diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 5a988778b23a..61da7dbe3ef4 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1,7 +1,10 @@ /* * u14-34f.c - Low-level SCSI driver for UltraStor 14F/34F * - * 28 Oct 1994 rev. 1.09 for linux 1.1.58 + * 14 Nov 1994 rev. 1.10 for linux 1.1.63 + * + * 28 Oct 1994 rev. 1.09 for linux 1.1.58 Final BETA release. + * 16 Jul 1994 rev. 1.00 for linux 1.1.29 Initial ALPHA release. * * This driver is a total replacement of the original UltraStor * scsi driver, but it supports ONLY the 14F and 34F boards. @@ -26,9 +29,9 @@ * * 14F - ISA first-party DMA HA with floppy support and WD1003 emulation. * 24F - EISA Bus Master HA with floppy support and WD1003 emulation. - * 34F - VL-Bus Bus Master HA with floppy support (no WD1003 emulation). + * 34F - VL-Bus Bus Master HA (no WD1003 emulation). * - * This code has been tested with up to two U14F on boards, using both + * This code has been tested with up to two U14F boards, using both * firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware * 28004-006/38004-005 (BIOS rev. 2.01). * @@ -69,7 +72,7 @@ * - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94; * - adapter_status equal 0 and target_status equal 2 on for all targets * in the next operation following the reset. - * This sequence takes a long time (>3 seconds), so in the mantime + * This sequence takes a long time (>3 seconds), so in the meantime * the SD_TIMEOUT in sd.c could expire giving rise to scsi aborts * (SD_TIMEOUT has been increased from 3 to 6 seconds in 1.1.31). * Because of this I had to DISABLE_CLUSTERING and to work around the @@ -77,7 +80,7 @@ * so that the operations are retried without complains from the scsi.c * code. * Any reset of the scsi bus is going to kill tape operations, since - * no retry is allowed for tapes. Bus resest are more likely when the + * no retry is allowed for tapes. Bus resets are more likely when the * scsi bus is under heavy load. * Requests using scatter/gather have a maximum length of 16 x 1024 bytes * when DISABLE_CLUSTERING is in effect, but unscattered requests could be @@ -136,13 +139,13 @@ #define DO_BUS_RESET /* Reset SCSI bus on error */ #define NO_DEBUG_DETECT #define NO_DEBUG_INTERRUPT -#define DEBUG_STATISTICS +#define NO_DEBUG_STATISTICS #define MAX_TARGET 8 #define MAX_IRQ 16 #define MAX_BOARDS 4 #define MAX_MAILBOXES 16 -#define MAX_SGLIST U34F_MAX_SGLIST +#define MAX_SGLIST 33 #define MAX_CMD_PER_LUN 2 #define FALSE 0 @@ -323,7 +326,7 @@ static inline int port_detect(ushort *port_base, unsigned int j, sh[j]->base = bios_segment_table[config_1.bios_segment]; sh[j]->irq = irq; sh[j]->this_id = config_2.ha_scsi_id; - sh[j]->hostt->can_queue = MAX_MAILBOXES; + sh[j]->can_queue = MAX_MAILBOXES; sh[j]->hostt->cmd_per_lun = MAX_CMD_PER_LUN; sys_mask = inb(sh[j]->io_port + REG_SYS_MASK); lcl_mask = inb(sh[j]->io_port + REG_LCL_MASK); @@ -336,11 +339,13 @@ static inline int port_detect(ushort *port_base, unsigned int j, if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK); #if defined (DO_BUS_RESET) - outb(lcl_mask | 0x40, sh[j]->io_port + REG_LCL_MASK); + lcl_mask = 0xc2; #else - outb(lcl_mask & ~0x40, sh[j]->io_port + REG_LCL_MASK); + lcl_mask = 0x82; #endif + outb(lcl_mask, sh[j]->io_port + REG_LCL_MASK); + /* Register the I/O space that we use */ snarf_region(sh[j]->io_port, REG_REGION); @@ -376,7 +381,7 @@ static inline int port_detect(ushort *port_base, unsigned int j, "Mbox %d, CmdLun %d, C%d.\n", BN(j), sh[j]->io_port, (int)sh[j]->base, sh[j]->irq, sh[j]->dma_channel, sh[j]->sg_tablesize, - sh[j]->hostt->can_queue, sh[j]->hostt->cmd_per_lun, + sh[j]->can_queue, sh[j]->hostt->cmd_per_lun, sh[j]->hostt->use_clustering); return TRUE; } @@ -447,9 +452,9 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { starting from last_cp_used */ i = HD(j)->last_cp_used + 1; - for(k = 0; k < sh[j]->hostt->can_queue; k++, i++) { + for(k = 0; k < sh[j]->can_queue; k++, i++) { - if (i >= sh[j]->hostt->can_queue) i = 0; + if (i >= sh[j]->can_queue) i = 0; if (HD(j)->cp_stat[i] == FREE) { HD(j)->last_cp_used = i; @@ -457,7 +462,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { } } - if (k == sh[j]->hostt->can_queue) { + if (k == sh[j]->can_queue) { printk("%s: qcomm, no free mailbox, reseting.\n", BN(j)); if (HD(j)->in_reset) @@ -542,7 +547,7 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) { printk("%s: abort, mbox %d, target %d, pid %ld.\n", BN(j), i, SCarg->target, SCarg->pid); - if (i >= sh[j]->hostt->can_queue) + if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); if (wait_on_busy(sh[j]->io_port)) { @@ -611,7 +616,7 @@ int u14_34f_reset(Scsi_Cmnd * SCarg) { for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE; - for (i = 0; i < sh[j]->hostt->can_queue; i++) { + for (i = 0; i < sh[j]->can_queue; i++) { if (HD(j)->cp_stat[i] == FREE) continue; @@ -657,7 +662,7 @@ int u14_34f_reset(Scsi_Cmnd * SCarg) { cli(); printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); - for (i = 0; i < sh[j]->hostt->can_queue; i++) { + for (i = 0; i < sh[j]->can_queue; i++) { /* Skip mailboxes already set free by interrupt */ if (HD(j)->cp_stat[i] != IN_RESET) continue; @@ -739,7 +744,7 @@ static void u14_34f_interrupt_handler(int irq) { i = spp - HD(j)->cp; - if (i >= sh[j]->hostt->can_queue) + if (i >= sh[j]->can_queue) panic("%s: ihdlr, invalid mscp address.\n", BN(j)); if (HD(j)->cp_stat[i] == LOCKED) { diff --git a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h index c1fcb6f70ab1..9a0b6ebbb243 100644 --- a/drivers/scsi/u14-34f.h +++ b/drivers/scsi/u14-34f.h @@ -11,7 +11,7 @@ int u14_34f_abort(Scsi_Cmnd *); int u14_34f_reset(Scsi_Cmnd *); int u14_34f_biosparam(Disk *, int, int *); -#define U14_34F_VERSION "1.09.01" +#define U14_34F_VERSION "1.10.01" #define ULTRASTOR_14_34F { \ NULL, \ diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 47a1370675e8..c1754e337b15 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -253,7 +253,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break; default: - printk("Bad logical zone size %d\n", s -> u.isofs_sb.s_log_zone_size = 10); + printk("Bad logical zone size %ld\n", s -> u.isofs_sb.s_log_zone_size); goto out; } @@ -274,7 +274,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data, printk("Max size:%ld Log zone size:%ld\n", s->u.isofs_sb.s_max_size, - s->u.isofs_sb.s_log_zone_size); + 1UL << s->u.isofs_sb.s_log_zone_size); printk("First datazone:%ld Root inode number %d\n", s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size, isonum_733 (rootp->extent) << s -> u.isofs_sb.s_log_zone_size); diff --git a/include/linux/resource.h b/include/linux/resource.h index fb3226db6825..93db09bc9f10 100644 --- a/include/linux/resource.h +++ b/include/linux/resource.h @@ -49,7 +49,7 @@ struct rusage { #ifdef notdef #define RLIMIT_MEMLOCK 6 /* max locked-in-memory address space*/ #define RLIMIT_NPROC 7 /* max number of processes */ -#define RLIMIT_OFILE 8 /* max number of open files */ +#define RLIMIT_NOFILE 8 /* max number of open files */ #endif #define RLIM_NLIMITS 6 diff --git a/kernel/sys.c b/kernel/sys.c index 5cfbdf3279db..1ce3ee3877af 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -396,6 +396,7 @@ asmlinkage int sys_brk(unsigned long brk) int freepages; unsigned long rlim; unsigned long newbrk, oldbrk; + struct vm_area_struct * vma; if (brk < current->mm->end_code) return current->mm->brk; @@ -421,6 +422,15 @@ asmlinkage int sys_brk(unsigned long brk) if (brk - current->mm->end_code > rlim || brk >= current->mm->start_stack - 16384) return current->mm->brk; + /* + * Check against existing mmap mappings. + */ + for (vma = current->mm->mmap; vma; vma = vma->vm_next) { + if (newbrk <= vma->vm_start) + break; + if (oldbrk < vma->vm_end) + return current->mm->brk; + } /* * stupid algorithm to decide if we have enough memory: while * simple, it hopefully works in most obvious cases.. Easy to diff --git a/net/inet/raw.c b/net/inet/raw.c index 8136a872ac9b..a7d94d8b53e1 100644 --- a/net/inet/raw.c +++ b/net/inet/raw.c @@ -25,6 +25,7 @@ * Alan Cox : Use ttl/tos * Alan Cox : Cleaned up old debugging * Alan Cox : Use new kernel side addresses + * Arnt Gulbrandsen : Fixed MSG_DONTROUTE in raw sockets. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -157,7 +158,7 @@ static int raw_sendto(struct sock *sk, unsigned char *from, * Check the flags. Only MSG_DONTROUTE is permitted. */ - if (flags&MSG_DONTROUTE) + if (flags & ~MSG_DONTROUTE) return(-EINVAL); /* * Get and verify the address. diff --git a/net/socket.c b/net/socket.c index 9ec8a50b8756..ad940519e874 100644 --- a/net/socket.c +++ b/net/socket.c @@ -186,17 +186,6 @@ static int get_fd(struct inode *inode) } -/* - * Reverses the action of get_fd() by releasing the file. it closes - * the descriptor, but makes sure it does nothing more. Called when - * an incomplete socket must be closed, along with sock_release(). - */ - -static inline void toss_fd(int fd) -{ - sys_close(fd); /* the count protects us from iput */ -} - /* * Go from an inode to its socket slot. */ @@ -743,7 +732,11 @@ static int sock_socketpair(int family, int type, int protocol, unsigned long uso er=verify_area(VERIFY_WRITE, usockvec, 2 * sizeof(int)); if(er) + { + sys_close(fd1); + sys_close(fd2); return er; + } put_fs_long(fd1, &usockvec[0]); put_fs_long(fd2, &usockvec[1]); -- 2.39.5