These patches fix a couple of things in the pl14 kernel. 1) The Adaptec 1542C should now work for all firmware settings, including the > 1Gb disk switch enabled, more than 2 disks and dynamic scan of scsi bus. If the > 1Gb firmware is enabled, the correct mapping should be returned to fdisk. 2) Disc change with scsi cdrom is now a little more reliable. 3) The iso filesystem had a few panics that were fixed so that a panic was no longer required. -Eric --- ./fs/isofs/rock.c.~1~ Fri Oct 22 17:08:53 1993 +++ ./fs/isofs/rock.c Wed Dec 15 00:03:32 1993 @@ -388,8 +388,10 @@ rpnt = 0; block = inode->i_ino >> bufbits; - if (!(bh=bread(inode->i_dev,block, bufsize))) - panic("unable to read i-node block"); + if (!(bh=bread(inode->i_dev,block, bufsize))) { + printk("unable to read i-node block"); + return NULL; + }; pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1)); @@ -399,8 +401,11 @@ cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL); memcpy(cpnt, bh->b_data, bufsize); brelse(bh); - if (!(bh = bread(inode->i_dev,++block, bufsize))) - panic("unable to read i-node block"); + if (!(bh = bread(inode->i_dev,++block, bufsize))) { + kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS); + printk("unable to read i-node block"); + return NULL; + }; memcpy((char *)cpnt+bufsize, bh->b_data, bufsize); pnt = ((unsigned char *) cpnt) + (inode->i_ino & (bufsize - 1)); raw_inode = ((struct iso_directory_record *) pnt); --- ./fs/isofs/inode.c.~1~ Tue Dec 14 23:56:49 1993 +++ ./fs/isofs/inode.c Wed Dec 15 00:04:40 1993 @@ -331,8 +331,10 @@ int i; block = inode->i_ino >> ISOFS_BUFFER_BITS(inode); - if (!(bh=bread(inode->i_dev,block, bufsize))) - panic("unable to read i-node block"); + if (!(bh=bread(inode->i_dev,block, bufsize))) { + printk("unable to read i-node block"); + goto fail; + }; pnt = ((unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1))); @@ -343,8 +345,11 @@ cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL); memcpy(cpnt, bh->b_data, bufsize); brelse(bh); - if (!(bh = bread(inode->i_dev,++block, bufsize))) - panic("unable to read i-node block"); + if (!(bh = bread(inode->i_dev,++block, bufsize))) { + kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS); + printk("unable to read i-node block"); + goto fail; + }; memcpy((char *)cpnt + bufsize, bh->b_data, bufsize); pnt = ((unsigned char *) cpnt + (inode->i_ino & (bufsize - 1))); @@ -391,10 +396,6 @@ inode->i_size &= 0x00ffffff; }; - if (isonum_723 (raw_inode->volume_sequence_number) != 1) { - printk("Multi volume CD somehow got mounted.\n"); - }; - if (raw_inode->interleave[0]) { printk("Interleaved files not (yet) supported.\n"); inode->i_size = 0; @@ -467,18 +468,35 @@ }; inode->i_op = NULL; - if (S_ISREG(inode->i_mode)) - inode->i_op = &isofs_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &isofs_dir_inode_operations; - else if (S_ISLNK(inode->i_mode)) - inode->i_op = &isofs_symlink_inode_operations; - else if (S_ISCHR(inode->i_mode)) - inode->i_op = &chrdev_inode_operations; - else if (S_ISBLK(inode->i_mode)) - inode->i_op = &blkdev_inode_operations; - else if (S_ISFIFO(inode->i_mode)) - init_fifo(inode); + if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && + isonum_723 (raw_inode->volume_sequence_number) != 1) { + printk("Multi volume CD somehow got mounted.\n"); + } else { + if (S_ISREG(inode->i_mode)) + inode->i_op = &isofs_file_inode_operations; + else if (S_ISDIR(inode->i_mode)) + inode->i_op = &isofs_dir_inode_operations; + else if (S_ISLNK(inode->i_mode)) + inode->i_op = &isofs_symlink_inode_operations; + else if (S_ISCHR(inode->i_mode)) + inode->i_op = &chrdev_inode_operations; + else if (S_ISBLK(inode->i_mode)) + inode->i_op = &blkdev_inode_operations; + else if (S_ISFIFO(inode->i_mode)) + init_fifo(inode); + } + return; + fail: + /* With a data error we return this information */ + inode->i_mtime = inode->i_atime = inode->i_ctime = 0; + inode->u.isofs_i.i_first_extent = 0; + inode->u.isofs_i.i_backlink = 0xffffffff; + inode->i_size = 0; + inode->i_nlink = 1; + inode->i_uid = inode->i_gid = 0; + inode->i_mode = S_IFREG; /*Regular file, noone gets to read*/ + inode->i_op = NULL; + return; } /* There are times when we need to know the inode number of a parent of --- ./drivers/scsi/sr.c.~1~ Tue Nov 30 22:37:02 1993 +++ ./drivers/scsi/sr.c Wed Dec 15 00:56:55 1993 @@ -101,7 +101,12 @@ }; retval = scsi_CDs[target].device->changed; - if(!flag) scsi_CDs[target].device->changed = 0; + if(!flag) { + scsi_CDs[target].device->changed = 0; + /* If the disk changed, the capacity will now be different, + so we force a re-read of this information */ + if (retval) scsi_CDs[target].needs_sector_size = 1; + }; return retval; } @@ -654,6 +659,8 @@ memset ((void *) &cmd[2], 0, 8); SCpnt->request.dev = 0xffff; /* Mark as really busy */ + memset(buffer, 0, 8); + scsi_do_cmd (SCpnt, (void *) cmd, (void *) buffer, 512, sr_init_done, SR_TIMEOUT, @@ -692,6 +699,7 @@ printk ("scd%d : unsupported sector size %d.\n", i, scsi_CDs[i].sector_size); scsi_CDs[i].capacity = 0; + scsi_CDs[i].needs_sector_size = 1; }; if(scsi_CDs[i].sector_size == 2048) scsi_CDs[i].capacity *= 4; --- ./drivers/scsi/aha1542.c.~1~ Tue Nov 30 22:36:45 1993 +++ ./drivers/scsi/aha1542.c Wed Dec 15 01:08:44 1993 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -50,8 +51,13 @@ #define DMA_MASK_REG 0xd4 #define CASCADE 0xc0 +#define BIOS_TRANSLATION_1632 0 /* Used by some old 1542A boards */ +#define BIOS_TRANSLATION_6432 1 /* Default case these days */ +#define BIOS_TRANSLATION_25563 2 /* Big disk case */ + struct aha1542_hostdata{ /* This will effectively start both of them at the first mailbox */ + int bios_translation; /* Mapping bios uses - for compatibility */ int aha1542_last_mbi_used; int aha1542_last_mbo_used; Scsi_Cmnd * SCint[AHA1542_MAILBOXES]; @@ -174,6 +180,10 @@ static int aha1542_test_port(int bse, struct Scsi_Host * shpnt) { int i; + unchar inquiry_cmd[] = {CMD_INQUIRY }; + unchar inquiry_result[4]; + unchar *cmdp; + int len; volatile int debug = 0; /* Quick and dirty test for presence of the card. */ @@ -195,6 +205,26 @@ debug = 2; /* Shouldn't have generated any interrupts during reset */ if (inb(INTRFLAGS(bse))&INTRMASK) goto fail; + + + /* Perform a host adapter inquiry instead so we do not need to set + up the mailboxes ahead of time */ + + aha1542_out(bse, inquiry_cmd, 1); + + debug = 3; + len = 4; + cmdp = &inquiry_result[0]; + + while (len--) + { + WAIT(STATUS(bse), DF, DF, 0); + *cmdp++ = inb(DATA(bse)); + } + + debug = 4; + +#if 0 setup_mailboxes(bse, shpnt); debug = 3; @@ -216,6 +246,7 @@ debug = 7; /* Is the answer correct? */ if (inb(DATA(bse)) != 42) goto fail; +#endif debug = 8; /* Reading port should reset DF */ @@ -656,8 +687,41 @@ return 0; } +/* This function should only be called for 1542C boards - we can detect + the special firmware settings and unlock the board */ + +static int aha1542_mbenable(int base) +{ + static unchar mbenable_cmd[3]; + static unchar mbenable_result[2]; + int retval; + + retval = BIOS_TRANSLATION_6432; + + mbenable_cmd[0]=CMD_EXTBIOS; + aha1542_out(base,mbenable_cmd,1); + aha1542_in(base,mbenable_result,2); + WAIT(INTRFLAGS(base),INTRMASK,HACC,0); + aha1542_intr_reset(base); + + if (mbenable_result[0] & 0x08) { + mbenable_cmd[0]=CMD_MBENABLE; + mbenable_cmd[1]=0; + mbenable_cmd[2]=mbenable_result[1]; + if(mbenable_result[1] & 1) retval = BIOS_TRANSLATION_25563; + aha1542_out(base,mbenable_cmd,3); + WAIT(INTRFLAGS(base),INTRMASK,HACC,0); + }; + while(0) { +fail: + printk("aha1542_mbenable: Mailbox init failed\n"); + } +aha1542_intr_reset(base); +return retval; +} + /* Query the board to find out if it is a 1542 or a 1740, or whatever. */ -static int aha1542_query(int base_io) +static int aha1542_query(int base_io, int * transl) { unchar inquiry_cmd[] = {CMD_INQUIRY }; unchar inquiry_result[4]; @@ -675,6 +739,8 @@ } aha1542_intr_reset(base_io); + *transl = BIOS_TRANSLATION_6432; /* Default case */ + /* For an AHA1740 series board, we ignore the board since there is a hardware bug which can lead to wrong blocks being returned if the board is operating in the 1542 emulation mode. Since there is an extended mode @@ -685,9 +751,13 @@ printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n"); return 1; }; + if (inquiry_result[0] == 0x44) { /* Detect 1542C */ + *transl = aha1542_mbenable(base_io); + }; return 0; } + /* return non-zero on detection */ int aha1542_detect(int hostnum) { @@ -694,6 +764,7 @@ unsigned char dma_chan; unsigned char irq_level; unsigned int base_io; + int trans; struct Scsi_Host * shpnt = NULL; int count = 0; int indx; @@ -727,7 +798,7 @@ } aha1542_intr_reset(base_io); } - if(aha1542_query(base_io)) goto unregister; + if(aha1542_query(base_io, &trans)) goto unregister; if (aha1542_getconfig(base_io, &irq_level, &dma_chan) == -1) goto unregister; @@ -764,6 +835,9 @@ shpnt->io_port = base_io; shpnt->dma_channel = dma_chan; shpnt->irq = irq_level; + HOSTDATA(shpnt)->bios_translation = trans; + if(trans == 2) + printk("aha1542.c: Using extended bios translation\n"); HOSTDATA(shpnt)->aha1542_last_mbi_used = (2*AHA1542_MAILBOXES - 1); HOSTDATA(shpnt)->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1); memset(HOSTDATA(shpnt)->SCint, 0, sizeof(HOSTDATA(shpnt)->SCint)); @@ -847,11 +921,30 @@ return 0; } +#ifdef CONFIG_BLK_DEV_SD +#include "sd.h" +#endif + int aha1542_biosparam(int size, int dev, int * ip) { - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; + int translation_algorithm; +#ifdef CONFIG_BLK_DEV_SD + Scsi_Device *disk; + + disk = rscsi_disks[MINOR(dev) >> 4].device; + translation_algorithm = HOSTDATA(disk->host)->bios_translation; + /* Should this be > 1024, or >= 1024? Enquiring minds want to know. */ + if((size>>11) > 1024 && translation_algorithm == 2) { + /* Someone please verify that this is the same as what DOS returns */ + ip[0] = 255; + ip[1] = 63; + ip[2] = size /255/63; + } else { + ip[0] = 64; + ip[1] = 32; + ip[2] = size >> 11; + }; /* if (ip[2] >= 1024) ip[2] = 1024; */ +#endif return 0; } --- ./drivers/scsi/aha1542.h.~1~ Tue Nov 30 22:36:28 1993 +++ ./drivers/scsi/aha1542.h Wed Dec 15 00:02:30 1993 @@ -74,6 +74,9 @@ #define CMD_RETSETUP 0x0d /* Return Setup Data */ #define CMD_ECHO 0x1f /* ECHO Command Data */ +#define CMD_EXTBIOS 0x28 /* Return extend bios information only 1542C */ +#define CMD_MBENABLE 0x29 /* Set Mailbox Interface enable only 1542C */ + /* Mailbox Definition 5.2.1 and 5.2.2 */ struct mailbox { unchar status; /* Command/Status */