home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 26 / CD_ASCQ_26_1295.iso / vrac / ptch1331.zip / PTCH1331.GZ / PTCH1331
Text File  |  1995-10-04  |  219KB  |  7,552 lines

  1. diff -u --recursive --new-file v1.3.30/linux/CREDITS linux/CREDITS
  2. --- v1.3.30/linux/CREDITS    Sat Sep  9 15:26:50 1995
  3. +++ linux/CREDITS    Wed Sep 27 15:57:55 1995
  4. @@ -648,7 +648,7 @@
  5.  S: USA
  6.  
  7.  N: Rick Miller
  8. -E: rick@discus.mil.wi.us
  9. +E: rick@digalogsys.com
  10.  D: Linux Device Registrar (Major/minor numbers), "au-play", "bwBASIC"
  11.  S: S78 W16203 Woods Road
  12.  S: Muskego, Wisconsin 53150
  13. @@ -753,7 +753,6 @@
  14.  N: Ken Pizzini
  15.  E: ken@halcyon.com
  16.  D: CDROM driver "sonycd535" (Sony CDU-535/531)
  17. -S: 
  18.  
  19.  N: Frederic Potter 
  20.  E: Frederic.Potter@masi.ibp.fr 
  21. diff -u --recursive --new-file v1.3.30/linux/Documentation/SMP.txt linux/Documentation/SMP.txt
  22. --- v1.3.30/linux/Documentation/SMP.txt    Thu Jan  1 02:00:00 1970
  23. +++ linux/Documentation/SMP.txt    Mon Oct  2 14:25:09 1995
  24. @@ -0,0 +1,38 @@
  25. +
  26. +SMP support for Linux with up to 32 processors using the Intel MP
  27. +specification. 
  28. +
  29. +WARNING:
  30. +    This is experimental. Back up your disks first. Build only
  31. +with gcc2.5.8.
  32. +
  33. +
  34. +To fix:
  35. +
  36. +o    Fix sys_idle to exit/enter kernel state and do hlt's.
  37. +o    Fix scheduler decisions to reschedule. Per cpu reschedule ?
  38. +o    Scheduler ignores stick to CPU advantage. Critical for P6!
  39. +o    FPU state save/restore - fault any process on FPU and do a
  40. +    restore on the fault each context switch, do a save if we
  41. +    faulted that run of the task when we switch away. [DONE]
  42. +o    Clean up message pass.
  43. +o    Test for B stepping processors.
  44. +o    Clean up processor specific/independant split.
  45. +o    Document it all.    [PARTLY DONE]
  46. +o    Find the exception/crash bug.
  47. +o    Halt other CPU's on reset/panic doesn't always work.
  48. +o    Dont waste page at 4K - dont need it now.(watch the GDT code).
  49. +o    Dump bootup pages once booted somehow.
  50. +o    Verify message pass safe for >2 CPU's - should be now it
  51. +    is atomic lock based.
  52. +o    Dont schedule switches between idle tasks (if current->pid==0 &&
  53. +    next->pid==0 && next!=current)    [IN]
  54. +o    Clean up warnings/volatiles.
  55. +o    Send CTRL-ALT-DEL to pid 1 not task[1]!    [IN]
  56. +o    Fix load_TR() for non contiguous processor ids
  57. +o    Iterate over the slave timer requests if one is lost (keep a count per cpu)
  58. +o    Distribute irq's (locking present just needs the 82489 to be asked
  59. +    nicely).
  60. +o    486 startup code.
  61. +o    How to handle mixed FPU/non FPU processors.
  62. +o    Support 4Mb page mode again
  63. diff -u --recursive --new-file v1.3.30/linux/Makefile linux/Makefile
  64. --- v1.3.30/linux/Makefile    Wed Sep 27 15:59:56 1995
  65. +++ linux/Makefile    Wed Sep 27 15:57:12 1995
  66. @@ -1,6 +1,6 @@
  67.  VERSION = 1
  68.  PATCHLEVEL = 3
  69. -SUBLEVEL = 30
  70. +SUBLEVEL = 31
  71.  
  72.  ARCH = i386
  73.  
  74. diff -u --recursive --new-file v1.3.30/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
  75. --- v1.3.30/linux/arch/alpha/kernel/entry.S    Wed Sep 13 12:45:29 1995
  76. +++ linux/arch/alpha/kernel/entry.S    Sat Sep 30 10:59:41 1995
  77. @@ -590,7 +590,7 @@
  78.      .quad sys_setsockopt, sys_listen, do_entSys, do_entSys, do_entSys
  79.      .quad do_entSys, sys_sigsuspend, do_entSys, do_entSys, do_entSys
  80.      .quad do_entSys, sys_gettimeofday, sys_getrusage, sys_getsockopt, do_entSys
  81. -    .quad do_entSys, do_entSys, sys_settimeofday, sys_fchown, sys_fchmod
  82. +    .quad sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
  83.      .quad sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
  84.      .quad sys_ftruncate, do_entSys, sys_setgid, sys_sendto, sys_shutdown
  85.      .quad sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, do_entSys
  86. @@ -629,6 +629,6 @@
  87.  /* linux-specific system calls start at 300 */
  88.  /*300*/    .quad sys_bdflush, sys_sethae, sys_mount, sys_adjtimex, sys_swapoff
  89.      .quad sys_getdents, sys_create_module, sys_init_module, sys_delete_module, sys_get_kernel_syms
  90. -    .quad sys_syslog, sys_reboot, sys_clone, do_entSys, do_entSys
  91. +    .quad sys_syslog, sys_reboot, sys_clone, sys_uselib, do_entSys
  92.      .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
  93.  
  94. diff -u --recursive --new-file v1.3.30/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
  95. --- v1.3.30/linux/arch/alpha/kernel/irq.c    Wed Sep 27 15:59:56 1995
  96. +++ linux/arch/alpha/kernel/irq.c    Wed Oct  4 07:44:44 1995
  97. @@ -24,6 +24,8 @@
  98.  #include <asm/bitops.h>
  99.  #include <asm/dma.h>
  100.  
  101. +extern void timer_interrupt(struct pt_regs * regs);
  102. +
  103.  static unsigned char cache_21 = 0xff;
  104.  static unsigned char cache_A1 = 0xff;
  105.  
  106. @@ -223,6 +225,9 @@
  107.  
  108.      if (irq >= NR_IRQS)
  109.          return -EINVAL;
  110. +    /* don't accept requests for irq #0 */
  111. +    if (!irq)
  112. +        return -EINVAL;
  113.      action = irq + irq_action;
  114.      if (action->handler)
  115.          return -EBUSY;
  116. @@ -282,12 +287,16 @@
  117.          if (irq_action[i].handler)
  118.              printk("[%s:%d] ", irq_action[i].name, i);
  119.      printk("\n");
  120. +#if defined(CONFIG_ALPHA_JENSEN)
  121.      printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
  122.          inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
  123.      outb(0x0c, 0x3fc);
  124.      outb(0x0c, 0x2fc);
  125.      outb(0,0x61);
  126.      outb(0,0x461);
  127. +#elif defined(CONFIG_ALPHA_NONAME)
  128. +    printk("61=%02x, 64=%02x, 60=%02x\n", inb(0x61), inb(0x64), inb(0x60));
  129. +#endif
  130.  }
  131.  
  132.  static inline void handle_irq(int irq, struct pt_regs * regs)
  133. @@ -563,8 +572,7 @@
  134.              printk("Interprocessor interrupt? You must be kidding\n");
  135.              break;
  136.          case 1:
  137. -            /* timer interrupt.. */
  138. -            handle_irq(0, ®s);
  139. +            timer_interrupt(®s);
  140.              return;
  141.          case 2:
  142.              machine_check(vector, la_ptr, ®s);
  143. diff -u --recursive --new-file v1.3.30/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c
  144. --- v1.3.30/linux/arch/alpha/kernel/lca.c    Sun Sep  3 12:26:48 1995
  145. +++ linux/arch/alpha/kernel/lca.c    Mon Oct  2 08:21:06 1995
  146. @@ -290,6 +290,9 @@
  147.      printk("esr=%lx, ear=%lx, ioc_stat0=%lx, ioc_stat1=%lx\n",
  148.             *(unsigned long*)LCA_MEM_ESR, *(unsigned long*)LCA_MEM_EAR,
  149.             *(unsigned long*)LCA_IOC_STAT0, *(unsigned long*)LCA_IOC_STAT1);
  150. +#ifdef CONFIG_ALPHA_NONAME
  151. +    printk("NMMI status & control (0x61)=%02x\n", inb(0x61));
  152. +#endif
  153.  }
  154.  
  155.  #endif /* CONFIG_ALPHA_LCA */
  156. diff -u --recursive --new-file v1.3.30/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
  157. --- v1.3.30/linux/arch/alpha/kernel/time.c    Wed Sep 27 15:59:56 1995
  158. +++ linux/arch/alpha/kernel/time.c    Wed Oct  4 07:43:36 1995
  159. @@ -32,7 +32,7 @@
  160.   * timer_interrupt() needs to keep up the real-time clock,
  161.   * as well as call the "do_timer()" routine every clocktick
  162.   */
  163. -static void timer_interrupt(int irq, struct pt_regs * regs)
  164. +void timer_interrupt(struct pt_regs * regs)
  165.  {
  166.      /* last time the cmos clock got updated */
  167.      static long last_rtc_update=0;
  168. @@ -130,8 +130,6 @@
  169.          year += 100;
  170.      xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
  171.      xtime.tv_usec = 0;
  172. -    if (request_irq(TIMER_IRQ, timer_interrupt, 0, "timer") != 0)
  173. -        panic("Could not allocate timer IRQ!");
  174.  }
  175.  
  176.  /*
  177. diff -u --recursive --new-file v1.3.30/linux/arch/i386/Makefile linux/arch/i386/Makefile
  178. --- v1.3.30/linux/arch/i386/Makefile    Fri Jul  7 08:54:44 1995
  179. +++ linux/arch/i386/Makefile    Mon Oct  2 15:12:14 1995
  180. @@ -91,6 +91,7 @@
  181.  
  182.  archclean:
  183.      @$(MAKEBOOT) clean
  184. +    $(MAKE) -C arch/$(ARCH)/kernel clean
  185.  
  186.  archdep:
  187.      @$(MAKEBOOT) dep
  188. diff -u --recursive --new-file v1.3.30/linux/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S
  189. --- v1.3.30/linux/arch/i386/boot/compressed/head.S    Thu Jun 29 19:02:39 1995
  190. +++ linux/arch/i386/boot/compressed/head.S    Mon Oct  2 14:25:09 1995
  191. @@ -9,7 +9,12 @@
  192.   *
  193.   * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
  194.   * the page directory will exist. The startup code will be overwritten by
  195. - * the page directory.
  196. + * the page directory. [According to comments etc elsewhere on a compressed
  197. + * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
  198. + *
  199. + * In SMP mode we keep this page safe. Really we ought to shuffle things and
  200. + * put the trampoline here. - AC. An SMP trampoline enters with %cx holding
  201. + * the stack base.
  202.   *
  203.   * Page 0 is deliberately kept safe, since System Management Mode code in 
  204.   * laptops may need to access the BIOS data stored there.  This is also
  205. @@ -19,10 +24,12 @@
  206.  .text
  207.  
  208.  #define __ASSEMBLY__
  209. +#include <linux/config.h>
  210.  #include <linux/linkage.h>
  211.  #include <asm/segment.h>
  212.  
  213.      .globl startup_32
  214. +    
  215.  startup_32:
  216.      cld
  217.      cli
  218. @@ -31,6 +38,24 @@
  219.      mov %ax,%es
  220.      mov %ax,%fs
  221.      mov %ax,%gs
  222. +#ifdef CONFIG_SMP
  223. +    orw %bx,%bx            # What state are we in BX=1 for SMP
  224. +                    # 0 for boot
  225. +    jz  2f                # Initial boot
  226. +
  227. +/*
  228. + *    We are trampolining an SMP processor
  229. + */
  230. +    mov %ax,%ss
  231. +    xorl %eax,%eax            # Back to 0
  232. +    mov  %cx,%ax            # SP low 16 bits
  233. +    movl %eax,%esp
  234. +    pushl 0                # Clear NT
  235. +    popfl
  236. +    ljmp $(KERNEL_CS), $0x100000    # Into C and sanity
  237. +
  238. +2:
  239. +#endif
  240.      lss SYMBOL_NAME(stack_start),%esp
  241.      xorl %eax,%eax
  242.  1:    incl %eax        # check that A20 really IS enabled
  243. @@ -58,4 +83,6 @@
  244.   * Do the decompression, and jump to the new kernel..
  245.   */
  246.      call SYMBOL_NAME(decompress_kernel)
  247. +    xorl %ebx,%ebx
  248.      ljmp $(KERNEL_CS), $0x100000
  249. +
  250. diff -u --recursive --new-file v1.3.30/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
  251. --- v1.3.30/linux/arch/i386/boot/setup.S    Tue Jun 20 09:10:31 1995
  252. +++ linux/arch/i386/boot/setup.S    Mon Oct  2 14:25:09 1995
  253. @@ -344,6 +344,7 @@
  254.      lmsw    ax        ! This is it!
  255.      jmp    flush_instr
  256.  flush_instr:
  257. +    mov    bx,#0        ! Flag to indicate a boot
  258.      jmpi    0x1000,KERNEL_CS    ! jmp offset 1000 of segment 0x10 (cs)
  259.  
  260.  ! This routine checks that the keyboard command queue is empty
  261. diff -u --recursive --new-file v1.3.30/linux/arch/i386/config.in linux/arch/i386/config.in
  262. --- v1.3.30/linux/arch/i386/config.in    Wed Sep 27 15:59:56 1995
  263. +++ linux/arch/i386/config.in    Tue Oct  3 12:43:53 1995
  264. @@ -40,6 +40,7 @@
  265.  #if [ "$CONFIG_M586" = "n" ]; then
  266.  bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y
  267.  #fi
  268. +bool 'SMP Kernel (experimental - gcc2.5.8 only: see Documentation/SMP.txt)' CONFIG_SMP n
  269.  
  270.  comment 'Loadable module support'
  271.  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS n
  272. @@ -74,6 +75,7 @@
  273.  if [ "$CONFIG_AX25" = "y" ]; then
  274.    bool 'Amateur Radio NET/ROM' CONFIG_NETROM n
  275.  fi
  276. +bool 'Kernel/User network link driver(ALPHA)' CONFIG_NETLINK n
  277.  fi
  278.  
  279.  comment 'SCSI support'
  280. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
  281. --- v1.3.30/linux/arch/i386/kernel/Makefile    Wed Sep 27 15:59:56 1995
  282. +++ linux/arch/i386/kernel/Makefile    Mon Oct  2 15:13:57 1995
  283. @@ -7,21 +7,51 @@
  284.  #
  285.  # Note 2! The CFLAGS definitions are now in the main makefile...
  286.  
  287. +AS86    =as86 -0 -a
  288. +AS386    =as86 -3
  289. +LD86    =ld86 -0
  290. +
  291. +
  292.  #.S.s:
  293.  #    $(CPP) -D__ASSEMBLY__ -traditional $< -o $*.s
  294.  .S.o:
  295.      $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
  296.  
  297.  all: kernel.o head.o
  298. +
  299.  O_TARGET := kernel.o
  300.  O_OBJS   := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \
  301.              ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o
  302.  
  303. -
  304. -#head.o: head.s
  305. +ifdef CONFIG_SMP
  306. +O_OBJS += smp.o
  307. +endif
  308.  
  309.  head.o: head.S $(TOPDIR)/include/linux/tasks.h
  310.      $(CC) -D__ASSEMBLY__ -traditional -c $*.S -o $*.o
  311. -#    $(CPP) -traditional -o $*.s $<
  312. +
  313. +hexify:
  314. +    $(HOSTCC) hexify.c -o hexify
  315. +
  316. +trampoline.hex: trampoline hexify
  317. +    (dd if=trampoline bs=1 skip=32 | ./hexify >trampoline.hex )
  318. +
  319. +trampoline: trampoline.o trampoline32.o
  320. +    $(LD86) -s -o $@ trampoline.o trampoline32.o
  321. +
  322. +trampoline.o: trampoline.s
  323. +    $(AS86) -o $@ $<
  324. +
  325. +trampoline32.o: trampoline32.s
  326. +    $(AS386) -o $@ $<
  327. +
  328. +trampoline.s: trampoline.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
  329. +    $(CPP) -traditional $< -o $@
  330. +
  331. +trampoline32.s: trampoline32.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
  332. +    $(CPP) -traditional $< -o $@
  333. +
  334. +clean:
  335. +    rm -f trampoline hexify
  336.  
  337.  include $(TOPDIR)/Rules.make
  338. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
  339. --- v1.3.30/linux/arch/i386/kernel/entry.S    Mon Aug 28 14:52:18 1995
  340. +++ linux/arch/i386/kernel/entry.S    Tue Oct  3 12:10:12 1995
  341. @@ -41,8 +41,11 @@
  342.   */
  343.  
  344.  #include <linux/sys.h>
  345. +#include <linux/config.h>
  346.  #include <linux/linkage.h>
  347.  #include <asm/segment.h>
  348. +#define ASSEMBLY
  349. +#include <asm/smp.h>
  350.  
  351.  EBX        = 0x00
  352.  ECX        = 0x04
  353. @@ -102,13 +105,112 @@
  354.      movl $(USER_DS),%edx; \
  355.      mov %dx,%fs;
  356.  
  357. +#ifdef    CONFIG_SMP
  358. +
  359. +#define GET_PROCESSOR_ID \
  360. +    movl SYMBOL_NAME(apic_reg), %edx; \
  361. +    movl 32(%edx), %eax;\
  362. +    movl %eax,SYMBOL_NAME(apic_retval); \
  363. +    shrl $24,%eax; \
  364. +    andb $0x0F,%al;
  365. +
  366. +/*
  367. + *    Get the processor ID multiplied by 4
  368. + */
  369. +
  370. +#define GET_PROCESSOR_OFFSET(x) \
  371. +    movl SYMBOL_NAME(apic_reg), x ; \
  372. +    movl 32( x ), x ; \
  373. +    shrl $22, x ; \
  374. +    andl $0x3C, x ;
  375. +
  376. +/* macro LEAVE_KERNEL decrements kernel_counter and resets kernel_flag and
  377. +   saves processor variables if zero */
  378. +#define    LEAVE_KERNEL \
  379. +    pushfl; \
  380. +    cli; \
  381. +    decl SYMBOL_NAME(syscall_count); \
  382. +    decl SYMBOL_NAME(kernel_counter); \
  383. +    jnz 1f;    \
  384. +    movb $(NO_PROC_ID), SYMBOL_NAME(active_kernel_processor); \
  385. +    lock; \
  386. +    btrl $0, SYMBOL_NAME(kernel_flag); \
  387. +1:    popfl;
  388. +
  389. +/* macro ENTER_KERNEL waits for entering the kernel, increments
  390. +   kernel_counter, and reloads the processor variables if necessary
  391. +   uses : %eax, %edx (pushed and popped) 
  392. +
  393. +   Note: We go to great pains to minimise the number of locked operations.
  394. +   We want to spin without locking, and lock when we attempt an update.
  395. +   The pentium has a MESI cache so the spin without lock will exit when
  396. +   another CPU write invalidates our cache, and the lock is avoided when
  397. +   possible so we don't play ping-pong games with the cache line.
  398. +
  399. +*/
  400. +
  401. +#define    ENTER_KERNEL \
  402. +    pushl %eax; \
  403. +    pushl %edx; \
  404. +    pushfl; \
  405. +    cli; \
  406. +    GET_PROCESSOR_ID \
  407. +1:    lock; \
  408. +    btsl $0, SYMBOL_NAME(kernel_flag); \
  409. +    jnc 3f; \
  410. +    cmpb SYMBOL_NAME(active_kernel_processor), %al; \
  411. +    je 4f; \
  412. +2:    incl SYMBOL_NAME(smp_spins); \
  413. +    btl %al, SYMBOL_NAME(smp_invalidate_needed); \
  414. +    jnc 5f; \
  415. +    lock; \
  416. +    btrl %al, SYMBOL_NAME(smp_invalidate_needed); \
  417. +    jnc 5f; \
  418. +    movl %cr3,%edx; \
  419. +    movl %edx,%cr3; \
  420. +5:    btl $0, SYMBOL_NAME(kernel_flag); \
  421. +    jc 2b; \
  422. +    jmp 1b; \
  423. +3:    movb %al, SYMBOL_NAME(active_kernel_processor); \
  424. +4:    incl SYMBOL_NAME(kernel_counter); \
  425. +    incl SYMBOL_NAME(syscall_count); \
  426. +    popfl; \
  427. +    popl %edx; \
  428. +    popl %eax;
  429. +
  430. +
  431. +#define RESTORE_ALL \
  432. +    cmpw $(KERNEL_CS),CS(%esp); \
  433. +    je 1f;   \
  434. +    GET_PROCESSOR_OFFSET(%edx) \
  435. +    movl SYMBOL_NAME(current_set)(,%edx), %eax ; ; \
  436. +    movl dbgreg7(%eax),%ebx; \
  437. +    movl %ebx,%db7;    \
  438. +1:    LEAVE_KERNEL \
  439. +    popl %ebx; \
  440. +    popl %ecx; \
  441. +    popl %edx; \
  442. +    popl %esi; \
  443. +    popl %edi; \
  444. +    popl %ebp; \
  445. +    popl %eax; \
  446. +    pop %ds; \
  447. +    pop %es; \
  448. +    pop %fs; \
  449. +    pop %gs; \
  450. +    addl $4,%esp; \
  451. +    iret
  452. +
  453. +#else
  454. +
  455.  #define RESTORE_ALL \
  456.      cmpw $(KERNEL_CS),CS(%esp); \
  457.      je 1f;   \
  458. -    movl SYMBOL_NAME(current),%eax; \
  459. +    movl SYMBOL_NAME(current_set),%eax; \
  460.      movl dbgreg7(%eax),%ebx; \
  461.      movl %ebx,%db7;    \
  462. -1:    popl %ebx; \
  463. +1:    \
  464. +    popl %ebx; \
  465.      popl %ecx; \
  466.      popl %edx; \
  467.      popl %esi; \
  468. @@ -121,11 +223,16 @@
  469.      pop %gs; \
  470.      addl $4,%esp; \
  471.      iret
  472. +#endif
  473. +
  474.  
  475.  ENTRY(lcall7)
  476.      pushfl            # We get a different stack layout with call gates,
  477.      pushl %eax        # which has to be cleaned up later..
  478.      SAVE_ALL
  479. +#ifdef CONFIG_SMP
  480. +    ENTER_KERNEL
  481. +#endif
  482.      movl EIP(%esp),%eax    # due to call gates, this is eflags, not eip..
  483.      movl CS(%esp),%edx    # this is eip..
  484.      movl EFLAGS(%esp),%ecx    # and this is cs..
  485. @@ -133,7 +240,12 @@
  486.      movl %edx,EIP(%esp)    # Now we move them to their "normal" places
  487.      movl %ecx,CS(%esp)    #
  488.      movl %esp,%eax
  489. -    movl SYMBOL_NAME(current),%edx
  490. +#ifdef CONFIG_SMP
  491. +    GET_PROCESSOR_OFFSET(%edx)    # Processor offset into edx
  492. +    movl SYMBOL_NAME(current_set)(,%edx),%edx
  493. +#else
  494. +    movl SYMBOL_NAME(current_set),%edx
  495. +#endif
  496.      pushl %eax
  497.      movl exec_domain(%edx),%edx    # Get the execution domain
  498.      movl 4(%edx),%edx    # Get the lcall7 handler for the domain
  499. @@ -153,18 +265,26 @@
  500.      ALIGN
  501.  reschedule:
  502.      pushl $ret_from_sys_call
  503. -    jmp SYMBOL_NAME(schedule)
  504. +    jmp SYMBOL_NAME(schedule)    # test
  505.  
  506.  ENTRY(system_call)
  507.      pushl %eax            # save orig_eax
  508.      SAVE_ALL
  509. +#ifdef CONFIG_SMP
  510. +    ENTER_KERNEL
  511. +#endif
  512.      movl $-ENOSYS,EAX(%esp)
  513.      cmpl $(NR_syscalls),%eax
  514.      jae ret_from_sys_call
  515.      movl SYMBOL_NAME(sys_call_table)(,%eax,4),%eax
  516.      testl %eax,%eax
  517.      je ret_from_sys_call
  518. -    movl SYMBOL_NAME(current),%ebx
  519. +#ifdef CONFIG_SMP
  520. +    GET_PROCESSOR_OFFSET(%edx)
  521. +    movl SYMBOL_NAME(current_set)(,%edx),%ebx
  522. +#else
  523. +    movl SYMBOL_NAME(current_set),%ebx
  524. +#endif
  525.      andl $~CF_MASK,EFLAGS(%esp)    # clear carry - assume no errors
  526.      movl $0,errno(%ebx)
  527.      movl %db6,%edx
  528. @@ -184,7 +304,12 @@
  529.      movl ORIG_EAX(%esp),%eax
  530.      call SYMBOL_NAME(sys_call_table)(,%eax,4)
  531.      movl %eax,EAX(%esp)        # save the return value
  532. -    movl SYMBOL_NAME(current),%eax
  533. +#ifdef CONFIG_SMP
  534. +    GET_PROCESSOR_OFFSET(%eax)
  535. +    movl SYMBOL_NAME(current_set)(,%eax),%eax
  536. +#else
  537. +    movl SYMBOL_NAME(current_set),%eax
  538. +#endif
  539.      movl errno(%eax),%edx
  540.      negl %edx
  541.      je 1f
  542. @@ -211,7 +336,12 @@
  543.      movl %eax,EFLAGS(%esp)        # stupid
  544.      cmpl $0,SYMBOL_NAME(need_resched)
  545.      jne reschedule
  546. -    movl SYMBOL_NAME(current),%eax
  547. +#ifdef CONFIG_SMP
  548. +    GET_PROCESSOR_OFFSET(%eax)
  549. +    movl SYMBOL_NAME(current_set)(,%eax), %eax
  550. +#else
  551. +    movl SYMBOL_NAME(current_set),%eax
  552. +#endif
  553.      cmpl SYMBOL_NAME(task),%eax    # task[0] cannot have signals
  554.      je 2f
  555.      cmpl $0,state(%eax)        # state
  556. @@ -277,8 +407,16 @@
  557.      mov %dx,%es
  558.      movl $(USER_DS),%edx
  559.      mov %dx,%fs
  560. +#ifdef CONFIG_SMP
  561. +    ENTER_KERNEL
  562. +#endif
  563.      pushl %eax
  564. -    movl SYMBOL_NAME(current),%eax
  565. +#ifdef CONFIG_SMP
  566. +    GET_PROCESSOR_OFFSET(%eax)
  567. +    movl SYMBOL_NAME(current_set)(,%eax), %eax
  568. +#else
  569. +    movl SYMBOL_NAME(current_set),%eax
  570. +#endif
  571.      movl %db6,%edx
  572.      movl %edx,dbgreg6(%eax)  # save current hardware debugging status
  573.      popl %eax
  574. @@ -294,6 +432,9 @@
  575.  ENTRY(device_not_available)
  576.      pushl $-1        # mark this as an int
  577.      SAVE_ALL
  578. +#ifdef CONFIG_SMP
  579. +    ENTER_KERNEL
  580. +#endif
  581.      pushl $ret_from_sys_call
  582.      movl %cr0,%eax
  583.      testl $0x4,%eax            # EM (math emulation bit)
  584. @@ -518,4 +659,6 @@
  585.      .long SYMBOL_NAME(sys_select)
  586.      .long SYMBOL_NAME(sys_flock)
  587.      .long SYMBOL_NAME(sys_msync)
  588. -    .space (NR_syscalls-144)*4
  589. +    .long SYMBOL_NAME(sys_readv)        /* 145 */
  590. +    .long SYMBOL_NAME(sys_writev)
  591. +    .space (NR_syscalls-146)*4
  592. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
  593. --- v1.3.30/linux/arch/i386/kernel/head.S    Thu Jun 29 19:02:39 1995
  594. +++ linux/arch/i386/kernel/head.S    Mon Oct  2 14:25:09 1995
  595. @@ -9,6 +9,7 @@
  596.   */
  597.  
  598.  .text
  599. +#include <linux/config.h>
  600.  #include <linux/tasks.h>
  601.  #include <linux/fd.h>
  602.  #include <linux/linkage.h>
  603. @@ -32,7 +33,22 @@
  604.      mov %ax,%es
  605.      mov %ax,%fs
  606.      mov %ax,%gs
  607. +#ifdef CONFIG_SMP
  608. +    orw  %bx,%bx
  609. +    jz  1f                /* Initial CPU cleans BSS */
  610. +/*
  611. + *    Set up the stack
  612. + */
  613. +    mov %ax,%ss
  614. +    xorl %eax,%eax
  615. +    movw %cx, %ax
  616. +    movl %eax,%esp
  617. +    pushl $0
  618. +    popfl
  619. +    jmp checkCPUtype
  620. +1:
  621.      lss stack_start,%esp
  622. +#endif CONFIG_SMP
  623.  /*
  624.   * Clear BSS first so that there are no surprises...
  625.   */
  626. @@ -84,6 +100,10 @@
  627.      rep
  628.      movsb
  629.  1:
  630. +#ifdef CONFIG_SMP
  631. +checkCPUtype:
  632. +#endif
  633. +
  634.  /* check if it is 486 or 386. */
  635.  /*
  636.   * XXX - this does a lot of unnecessary setup.  Alignment checks don't
  637. @@ -150,7 +170,32 @@
  638.      orl $2,%eax        # set MP
  639.  2:    movl %eax,%cr0
  640.      call check_x87
  641. +#ifdef CONFIG_SMP
  642. +    movb ready,%eax
  643. +    orb %eax,%eax
  644. +    jz 3f    
  645. +    movl $ SYMBOL_NAME(swapper_pg_dir), %eax
  646. +    movl %eax, %cr3
  647. +#ifdef GAS_KNOWS_CR4
  648. +    movl %cr4,%eax
  649. +    orl $16,%eax
  650. +    movl %eax,%cr4
  651. +#else
  652. +    .byte 0x0f,0x20,0xe0
  653. +    orl $16,%eax
  654. +    .byte 0x0f,0x22,0xe0
  655. +#endif
  656. +    movl %cr0, %eax
  657. +    orl $0x80000000, %eax
  658. +    movl %eax, %cr0
  659. +    jmp 4f
  660. +#endif
  661. +3:
  662.      call setup_paging
  663. +#ifdef CONFIG_SMP
  664. +    incb ready
  665. +#endif
  666. +4:
  667.      lgdt gdt_descr
  668.      lidt idt_descr
  669.      ljmp $(KERNEL_CS),$1f
  670. @@ -159,7 +204,12 @@
  671.      mov %ax,%es
  672.      mov %ax,%fs
  673.      mov %ax,%gs
  674. -    lss stack_start,%esp
  675. +#ifdef CONFIG_SMP
  676. +    movl $(KERNEL_DS), %eax
  677. +    mov  %ax,%ss        # Reload the stack pointer (segment only)
  678. +#else
  679. +    lss stack_start,%esp    # Load processor stack
  680. +#endif
  681.      xorl %eax,%eax
  682.      lldt %ax
  683.      pushl %eax        # These are the parameters to main :-)
  684. @@ -170,6 +220,10 @@
  685.  L6:
  686.      jmp L6            # main should never return here, but
  687.                  # just in case, we know what happens.
  688. +
  689. +#ifdef CONFIG_SMP
  690. +ready:    .byte 0
  691. +#endif
  692.  
  693.  /*
  694.   * We depend on ET to be correct. This checks for 287/387.
  695. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/hexify.c linux/arch/i386/kernel/hexify.c
  696. --- v1.3.30/linux/arch/i386/kernel/hexify.c    Thu Jan  1 02:00:00 1970
  697. +++ linux/arch/i386/kernel/hexify.c    Mon Oct  2 14:25:10 1995
  698. @@ -0,0 +1,31 @@
  699. +#include <stdio.h>
  700. +
  701. +
  702. +void main()
  703. +{
  704. +    int c;
  705. +    int comma=0;
  706. +    int count=0;
  707. +    while((c=getchar())!=EOF)
  708. +    {
  709. +        unsigned char x=c;
  710. +        if(comma)
  711. +            printf(",");
  712. +        else
  713. +            comma=1;
  714. +        if(count==8)
  715. +        {
  716. +            count=0;
  717. +            printf("\n");
  718. +        }
  719. +        if(count==0)
  720. +            printf("\t");
  721. +        printf("0x%02X",c);
  722. +        count++;
  723. +    }
  724. +    if(count)
  725. +        printf("\n");
  726. +    exit(0);
  727. +}
  728. +
  729. +        
  730. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
  731. --- v1.3.30/linux/arch/i386/kernel/irq.c    Wed Sep 27 15:59:56 1995
  732. +++ linux/arch/i386/kernel/irq.c    Mon Oct  2 14:25:09 1995
  733. @@ -15,6 +15,7 @@
  734.   * Naturally it's not a 1:1 relation, but there are similarities.
  735.   */
  736.  
  737. +#include <linux/config.h>
  738.  #include <linux/ptrace.h>
  739.  #include <linux/errno.h>
  740.  #include <linux/kernel_stat.h>
  741. @@ -29,6 +30,7 @@
  742.  #include <asm/io.h>
  743.  #include <asm/irq.h>
  744.  #include <asm/bitops.h>
  745. +#include <asm/smp.h>
  746.  
  747.  #define CR0_NE 32
  748.  
  749. @@ -103,19 +105,29 @@
  750.  BUILD_IRQ(SECOND,10,0x04)
  751.  BUILD_IRQ(SECOND,11,0x08)
  752.  BUILD_IRQ(SECOND,12,0x10)
  753. +#ifdef CONFIG_SMP
  754. +BUILD_MSGIRQ(SECOND,13,0x20)
  755. +#else
  756.  BUILD_IRQ(SECOND,13,0x20)
  757. +#endif
  758.  BUILD_IRQ(SECOND,14,0x40)
  759.  BUILD_IRQ(SECOND,15,0x80)
  760. +#ifdef CONFIG_SMP
  761. +BUILD_RESCHEDIRQ(16)
  762. +#endif
  763.  
  764.  /*
  765.   * Pointers to the low-level handlers: first the general ones, then the
  766.   * fast ones, then the bad ones.
  767.   */
  768. -static void (*interrupt[16])(void) = {
  769. +static void (*interrupt[17])(void) = {
  770.      IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
  771.      IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
  772.      IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
  773. -    IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
  774. +    IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt    
  775. +#ifdef CONFIG_SMP    
  776. +    ,IRQ16_interrupt
  777. +#endif
  778.  };
  779.  
  780.  static void (*fast_interrupt[16])(void) = {
  781. @@ -169,11 +181,20 @@
  782.      for (i = 0 ; i < 16 ; i++, action++) {
  783.          if (!action->handler)
  784.              continue;
  785. -        len += sprintf(buf+len, "%2d: %8d %c %s\n",
  786. +        len += sprintf(buf+len, "%3d: %8d %c %s\n",
  787.              i, kstat.interrupts[i],
  788.              (action->flags & SA_INTERRUPT) ? '+' : ' ',
  789.              action->name);
  790.      }
  791. +/*
  792. + *    Linus - should you add NMI counts here ?????
  793. + */
  794. +#ifdef CONFIG_SMP
  795. +    len+=sprintf(buf+len, "IPI: %8lu received\n",
  796. +        ipi_count);
  797. +    len+=sprintf(buf+len, "LCK: %8lu spins\n",
  798. +        smp_spins);
  799. +#endif        
  800.      return len;
  801.  }
  802.  
  803. @@ -187,6 +208,10 @@
  804.  asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
  805.  {
  806.      struct irqaction * action = irq + irq_action;
  807. +#ifdef CONFIG_SMP
  808. +    if(smp_threads_ready && active_kernel_processor!=smp_processor_id())
  809. +        panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
  810. +#endif
  811.  
  812.      kstat.interrupts[irq]++;
  813.  #ifdef CONFIG_RANDOM
  814. @@ -204,6 +229,11 @@
  815.  asmlinkage void do_fast_IRQ(int irq)
  816.  {
  817.      struct irqaction * action = irq + irq_action;
  818. +#ifdef CONFIG_SMP
  819. +    /* IRQ 13 is allowed - thats an invalidate */
  820. +    if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
  821. +        panic("fast_IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
  822. +#endif
  823.  
  824.      kstat.interrupts[irq]++;
  825.  #ifdef CONFIG_RANDOM
  826. @@ -283,6 +313,8 @@
  827.      restore_flags(flags);
  828.  }
  829.  
  830. +#ifndef CONFIG_SMP
  831. +
  832.  /*
  833.   * Note that on a 486, we don't want to do a SIGFPE on a irq13
  834.   * as the irq is unreliable, and exception 16 works correctly
  835. @@ -294,6 +326,8 @@
  836.   * leads to races. IBM designers who came up with it should
  837.   * be shot.
  838.   */
  839. +
  840.  static void math_error_irq(int cpl, struct pt_regs *regs)
  841.  {
  842.      outb(0,0xF0);
  843. @@ -302,6 +336,8 @@
  844.      math_error();
  845.  }
  846.  
  847. +#endif
  848. +
  849.  static void no_action(int cpl, struct pt_regs * regs) { }
  850.  
  851.  unsigned long probe_irq_on (void)
  852. @@ -359,6 +395,10 @@
  853.  void init_IRQ(void)
  854.  {
  855.      int i;
  856. +    static unsigned char smptrap=0;
  857. +    if(smptrap)
  858. +        return;
  859. +    smptrap=1;
  860.  
  861.      /* set the clock to 100 Hz */
  862.      outb_p(0x34,0x43);        /* binary, mode 2, LSB/MSB, ch 0 */
  863. @@ -366,10 +406,20 @@
  864.      outb(LATCH >> 8 , 0x40);    /* MSB */
  865.      for (i = 0; i < 16 ; i++)
  866.          set_intr_gate(0x20+i,bad_interrupt[i]);
  867. +    /* This bit is a hack because we don't send timer messages to all processors yet */
  868. +    /* It has to here .. it doesnt work if you put it down the bottom - assembler explodes 8) */
  869. +#ifdef CONFIG_SMP    
  870. +    set_intr_gate(0x20+i, interrupt[i]);    /* IRQ '16' - IPI for rescheduling */
  871. +#endif    
  872.      if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
  873. -        printk("Unable to get IRQ2 for cascade\n");
  874. +        printk("Unable to get IRQ2 for cascade.\n");
  875. +#ifndef CONFIG_SMP        
  876.      if (request_irq(13,math_error_irq, 0, "math error"))
  877. -        printk("Unable to get IRQ13 for math-error handler\n");
  878. +        printk("Unable to get IRQ13 for math-error handler.\n");
  879. +#else
  880. +    if (request_irq(13, smp_message_irq, SA_INTERRUPT, "IPI"))
  881. +        printk("Unable to get IRQ13 for IPI.\n");
  882. +#endif                
  883.      request_region(0x20,0x20,"pic1");
  884.      request_region(0xa0,0x20,"pic2");
  885.  } 
  886. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
  887. --- v1.3.30/linux/arch/i386/kernel/process.c    Wed Sep 13 12:45:29 1995
  888. +++ linux/arch/i386/kernel/process.c    Mon Oct  2 14:25:09 1995
  889. @@ -8,6 +8,7 @@
  890.   * This file handles the architecture-dependent parts of process handling..
  891.   */
  892.  
  893. +#include <linux/config.h>
  894.  #include <linux/errno.h>
  895.  #include <linux/sched.h>
  896.  #include <linux/kernel.h>
  897. @@ -24,6 +25,8 @@
  898.  #include <asm/pgtable.h>
  899.  #include <asm/system.h>
  900.  #include <asm/io.h>
  901. +#include <linux/smp.h>
  902. +
  903.  
  904.  asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
  905.  
  906. @@ -45,12 +48,40 @@
  907.  asmlinkage int sys_idle(void)
  908.  {
  909.      if (current->pid != 0)
  910. +    {
  911. +    /*    printk("Wrong process idled\n");    SMP bug check */
  912.          return -EPERM;
  913. -
  914. +    }
  915. +#ifdef CONFIG_SMP
  916. +    /*
  917. +     *    SMP locking sanity checker
  918. +     */
  919. +    if(smp_processor_id()!=active_kernel_processor)
  920. +        panic("CPU is %d, kernel CPU is %d in sys_idle!\n",
  921. +            smp_processor_id(), active_kernel_processor);
  922. +    if(syscall_count!=1)
  923. +        printk("sys_idle: syscall count is not 1 (%ld)\n", syscall_count);
  924. +    if(kernel_counter!=1)
  925. +    {
  926. +        printk("CPU %d, sys_idle, kernel_counter is %ld\n", smp_processor_id(), kernel_counter);
  927. +        if(!kernel_counter)
  928. +            panic("kernel locking botch");
  929. +    }
  930. +    /*
  931. +     *    Until we have C unlocking done
  932. +     */
  933. +    current->counter = -100;
  934. +    schedule();
  935. +    return 0;
  936. +#endif    
  937.      /* endless idle loop with no priority at all */
  938.      current->counter = -100;
  939.      for (;;) {
  940. +#ifdef CONFIG_SMP
  941. +        if (cpu_data[smp_processor_id()].hlt_works_ok && !hlt_counter && !need_resched)
  942. +#else    
  943.          if (hlt_works_ok && !hlt_counter && !need_resched)
  944. +#endif        
  945.              __asm__("hlt");
  946.          schedule();
  947.      }
  948. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
  949. --- v1.3.30/linux/arch/i386/kernel/setup.c    Mon Sep 25 12:26:21 1995
  950. +++ linux/arch/i386/kernel/setup.c    Mon Oct  2 14:25:09 1995
  951. @@ -26,6 +26,7 @@
  952.  
  953.  #include <asm/segment.h>
  954.  #include <asm/system.h>
  955. +#include <asm/smp.h>
  956.  
  957.  /*
  958.   * Tell us the machine setup..
  959. @@ -83,6 +84,13 @@
  960.      unsigned long memory_start, memory_end;
  961.      char c = ' ', *to = command_line, *from = COMMAND_LINE;
  962.      int len = 0;
  963. +    static unsigned char smptrap=0;
  964. +
  965. +    if(smptrap==1)
  966. +    {
  967. +        return;
  968. +    }
  969. +    smptrap=1;
  970.  
  971.       ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
  972.       drive_info = DRIVE_INFO;
  973. @@ -148,9 +156,10 @@
  974.  {
  975.      static const char *model[2][9]={{"DX","SX","DX/2","4","SX/2","6",
  976.                  "DX/2-WB","DX/4"},
  977. -            {"Pentium 60/66","Pentium 90/100","3",
  978. +            {"Pentium 60/66","Pentium 75+","3",
  979.                  "4","5","6","7","8"}};
  980.      char mask[2];
  981. +#ifndef CONFIG_SMP    
  982.      mask[0] = x86_mask+'@';
  983.      mask[1] = '\0';
  984.      return sprintf(buffer,"cpu\t\t: %c86\n"
  985. @@ -188,4 +197,90 @@
  986.                    x86_capability & 256 ? "yes" : "no",
  987.                        loops_per_sec/500000, (loops_per_sec/5000) % 100
  988.                    );
  989. +#else
  990. +    char *bp=buffer;
  991. +    int i;    
  992. +    bp+=sprintf(bp,"cpu\t\t: ");
  993. +    for(i=0;i<32;i++)
  994. +        if(cpu_present_map&(1<<i))
  995. +            bp+=sprintf(bp,"%c86             ",cpu_data[i].x86+'0');
  996. +    bp+=sprintf(bp,"\nmodel\t\t: ");
  997. +    for(i=0;i<32;i++)
  998. +        if(cpu_present_map&(1<<i))
  999. +            bp+=sprintf(bp,"%-16s",cpu_data[i].x86_model?
  1000. +                    model[cpu_data[i].x86-4][cpu_data[i].x86_model-1]:"Unknown");
  1001. +    bp+=sprintf(bp,"\nmask\t\t: ");
  1002. +    for(i=0;i<32;i++)
  1003. +        if(cpu_present_map&(1<<i))
  1004. +        {
  1005. +            mask[0] = cpu_data[i].x86_mask+'@';
  1006. +            mask[1] = '\0';        
  1007. +            bp+=sprintf(bp,"%-16s", cpu_data[i].x86_mask ? mask : "Unknown");
  1008. +        }
  1009. +    bp+=sprintf(bp,"\nvid\t\t: ");
  1010. +    for(i=0;i<32;i++)
  1011. +        if(cpu_present_map&(1<<i))
  1012. +            bp+=sprintf(bp,"%-16s", cpu_data[i].x86_vendor_id);
  1013. +    bp+=sprintf(bp,"\nfdiv_bug\t: ");
  1014. +    for(i=0;i<32;i++)
  1015. +        if(cpu_present_map&(1<<i))
  1016. +            bp+=sprintf(bp,"%-16s", cpu_data[i].fdiv_bug?"yes":"no");
  1017. +    bp+=sprintf(bp,"\nmath\t\t: ");
  1018. +    for(i=0;i<32;i++)
  1019. +        if(cpu_present_map&(1<<i))
  1020. +            bp+=sprintf(bp,"%-16s", cpu_data[i].hard_math?"yes":"no");
  1021. +    bp+=sprintf(bp,"\nhlt\t\t: ");
  1022. +    for(i=0;i<32;i++)
  1023. +        if(cpu_present_map&(1<<i))
  1024. +            bp+=sprintf(bp,"%-16s", cpu_data[i].hlt_works_ok?"yes":"no");
  1025. +    bp+=sprintf(bp,"\nwp\t\t: ");
  1026. +    for(i=0;i<32;i++)
  1027. +        if(cpu_present_map&(1<<i))
  1028. +            bp+=sprintf(bp,"%-16s", cpu_data[i].wp_works_ok?"yes":"no");
  1029. +    bp+=sprintf(bp,"\nIntegrated NPU\t: ");
  1030. +    for(i=0;i<32;i++)
  1031. +        if(cpu_present_map&(1<<i))
  1032. +            bp+=sprintf(bp,"%-16s", cpu_data[i].x86_capability&1?"yes":"no");
  1033. +    bp+=sprintf(bp,"\nEnhanced VM86\t: ");
  1034. +    for(i=0;i<32;i++)
  1035. +        if(cpu_present_map&(1<<i))
  1036. +            bp+=sprintf(bp,"%-16s", cpu_data[i].x86_capability&2?"yes":"no");
  1037. +    bp+=sprintf(bp,"\nIO Breakpoints\t: ");
  1038. +    for(i=0;i<32;i++)
  1039. +        if(cpu_present_map&(1<<i))
  1040. +            bp+=sprintf(bp,"%-16s", (cpu_data[i].x86_capability&4)?"yes":"no");
  1041. +    bp+=sprintf(bp,"\n4MB Pages\t: ");
  1042. +    for(i=0;i<32;i++)
  1043. +        if(cpu_present_map&(1<<i))
  1044. +            bp+=sprintf(bp,"%-16s", (cpu_data[i].x86_capability)&8?"yes":"no");
  1045. +    bp+=sprintf(bp,"\nTS Counters\t: ");
  1046. +    for(i=0;i<32;i++)
  1047. +        if(cpu_present_map&(1<<i))
  1048. +            bp+=sprintf(bp,"%-16s", (cpu_data[i].x86_capability&16)?"yes":"no");
  1049. +    bp+=sprintf(bp,"\nPentium MSR\t: ");
  1050. +    for(i=0;i<32;i++)
  1051. +        if(cpu_present_map&(1<<i))
  1052. +            bp+=sprintf(bp,"%-16s", (cpu_data[i].x86_capability&32)?"yes":"no");
  1053. +    bp+=sprintf(bp,"\nMach. Ch. Exep.\t: ");
  1054. +    for(i=0;i<32;i++)
  1055. +        if(cpu_present_map&(1<<i))
  1056. +            bp+=sprintf(bp,"%-16s", (cpu_data[i].x86_capability&128)?"yes":"no");
  1057. +    bp+=sprintf(bp,"\nCMPXCHG8B\t: ");
  1058. +    for(i=0;i<32;i++)
  1059. +        if(cpu_present_map&(1<<i))
  1060. +            bp+=sprintf(bp,"%-16s", (cpu_data[i].x86_capability&256)?"yes":"no");
  1061. +    bp+=sprintf(bp,"\nBogoMips\t: ");
  1062. +    for(i=0;i<32;i++)
  1063. +    {
  1064. +        char tmp[17];
  1065. +        if(cpu_present_map&(1<<i))
  1066. +        {
  1067. +            sprintf(tmp,"%lu.%02lu",cpu_data[i].udelay_val/500000L,
  1068. +                           (cpu_data[i].udelay_val/5000L)%100);
  1069. +            bp+=sprintf(bp,"%-16s",tmp);
  1070. +        }
  1071. +    }
  1072. +    *bp++='\n';
  1073. +    return bp-buffer;
  1074. +#endif                  
  1075.  }
  1076. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
  1077. --- v1.3.30/linux/arch/i386/kernel/smp.c    Thu Jan  1 02:00:00 1970
  1078. +++ linux/arch/i386/kernel/smp.c    Mon Oct  2 15:07:01 1995
  1079. @@ -0,0 +1,918 @@
  1080. +/*
  1081. + *    Intel MP v1.1 specification support routines for multi-pentium 
  1082. + *    hosts.
  1083. + *
  1084. + *    (c) 1995 Alan Cox, CymruNET Ltd  <alan@cymru.net>
  1085. + *    Supported by Caldera http://www.caldera.com.
  1086. + *    Much of the core SMP work is based on previous work by Thomas Radke, to
  1087. + *    whom a great many thanks are extended.
  1088. + *
  1089. + *    This code is released under the GNU public license version 2 or
  1090. + *    later.
  1091. + *
  1092. + *    Fixes
  1093. + *        Felix Koop:    NR_CPUS used properly
  1094. + *
  1095. + */
  1096. +
  1097. +#include <linux/kernel.h>
  1098. +#include <linux/string.h>
  1099. +#include <linux/config.h>
  1100. +#include <linux/timer.h>
  1101. +#include <linux/sched.h>
  1102. +#include <linux/mm.h>
  1103. +#include <linux/kernel_stat.h>
  1104. +#include <linux/delay.h>
  1105. +#include <asm/i82489.h>
  1106. +#include <linux/smp.h>
  1107. +#include <asm/bitops.h>
  1108. +#include <asm/smp.h>
  1109. +
  1110. +extern void *vremap(unsigned long offset, unsigned long size);    /* Linus hasnt put this in the headers yet */
  1111. +
  1112. +static int smp_found_config=0;                /* Have we found an SMP box                 */
  1113. +
  1114. +unsigned long cpu_present_map = 0;            /* Bitmask of existing CPU's                 */
  1115. +int smp_num_cpus;                    /* Total count of live CPU's                 */
  1116. +int smp_threads_ready=0;                /* Set when the idlers are all forked             */
  1117. +volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};    /* We always use 0 the rest is ready for parallel delivery */
  1118. +volatile unsigned long smp_invalidate_needed;        /* Used for the invalidate map thats also checked in the spinlock */
  1119. +struct cpuinfo_x86 cpu_data[NR_CPUS];            /* Per cpu bogomips and other parameters         */
  1120. +static unsigned int num_processors = 0;            /* Internal processor count                */
  1121. +static unsigned long io_apic_addr = 0;            /* Address of the I/O apic (not yet used)         */
  1122. +unsigned char boot_cpu_id = 0;                /* Processor that is doing the boot up             */
  1123. +static unsigned char *kstack_base,*kstack_end;        /* Kernel stack list pointers                 */
  1124. +static int smp_activated = 0;                /* Tripped once we need to start cross invalidating     */
  1125. +static volatile int smp_commenced=0;            /* Tripped when we start scheduling                 */
  1126. +static unsigned char nlong=0;                /* Apparent value for boot CPU                 */
  1127. +unsigned char *apic_reg=((unsigned char *)&nlong)-0x20;    /* Later set to the vremap() of the APIC         */
  1128. +unsigned long apic_retval;                /* Just debugging the assembler..             */
  1129. +unsigned char *kernel_stacks[NR_CPUS];            /* Kernel stack pointers for CPU's (debugging)        */
  1130. +
  1131. +static volatile unsigned char smp_cpu_in_msg[NR_CPUS];    /* True if this processor is sending an IPI        */
  1132. +static volatile unsigned long smp_msg_data;        /* IPI data pointer                    */
  1133. +static volatile int smp_src_cpu;            /* IPI sender processor                    */
  1134. +static volatile int smp_msg_id;                /* Message being sent                    */
  1135. +
  1136. +volatile unsigned long kernel_flag=0;            /* Kernel spinlock                     */
  1137. +volatile unsigned char active_kernel_processor = NO_PROC_ID;    /* Processor holding kernel spinlock        */
  1138. +volatile unsigned long kernel_counter=0;        /* Number of times the processor holds the lock        */
  1139. +volatile unsigned long syscall_count=0;        /* Number of times the processor holds the syscall lock    */
  1140. +volatile unsigned long smp_spins=0;            /* Count of cycles wasted to spinning            */
  1141. +
  1142. +volatile unsigned long ipi_count;            /* Number of IPI's delivered                */
  1143. +
  1144. +/* 
  1145. + *    Checksum an MP configuration block.
  1146. + */
  1147. +static int mpf_checksum(unsigned char *mp, int len)
  1148. +{
  1149. +    int sum=0;
  1150. +    while(len--)
  1151. +        sum+=*mp++;
  1152. +    return sum&0xFF;
  1153. +}
  1154. +
  1155. +/*
  1156. + *    Processor encoding in an MP configuration block
  1157. + */
  1158. +static char *mpc_family(int family,int model)
  1159. +{
  1160. +    static char n[32];
  1161. +    static char *model_defs[]=
  1162. +    {
  1163. +        "80486DX","80486DX",
  1164. +        "80486SX","80486DX/2 or 80487",
  1165. +        "80486SL","Intel5X2(tm)",
  1166. +        "Unknown","Unknown",
  1167. +        "80486DX/4"
  1168. +    };
  1169. +    if(family==0x5)
  1170. +        return("Pentium(tm)");
  1171. +    if(family==0x0F && model==0x0F)
  1172. +        return("Special controller");
  1173. +    if(family==0x04 && model<9)
  1174. +        return model_defs[model];
  1175. +    sprintf(n,"Unknown CPU [%d:%d]",family, model);
  1176. +    return n;
  1177. +}
  1178. +
  1179. +/*
  1180. + *    Read the MPC
  1181. + */
  1182. +
  1183. +static int smp_read_mpc(struct mp_config_table *mpc)
  1184. +{
  1185. +    char str[16];
  1186. +    int count=sizeof(*mpc);
  1187. +    int apics=0;
  1188. +    unsigned char *mpt=((unsigned char *)mpc)+count;
  1189. +
  1190. +    if(memcmp(mpc->mpc_signature,MPC_SIGNATURE,4))
  1191. +    {
  1192. +        printk("Bad signature [%c%c%c%c].\n",
  1193. +            mpc->mpc_signature[0],
  1194. +            mpc->mpc_signature[1],
  1195. +            mpc->mpc_signature[2],
  1196. +            mpc->mpc_signature[3]);
  1197. +        return 1;
  1198. +    }
  1199. +    if(mpf_checksum((unsigned char *)mpc,mpc->mpc_length))
  1200. +    {
  1201. +        printk("Checksum error.\n");
  1202. +        return 1;
  1203. +    }
  1204. +    if(mpc->mpc_spec!=0x01)
  1205. +    {
  1206. +        printk("Unsupported version (%d)\n",mpc->mpc_spec);
  1207. +        return 1;
  1208. +    }
  1209. +    memcpy(str,mpc->mpc_oem,8);
  1210. +    str[8]=0;
  1211. +    printk("OEM ID: %s ",str);
  1212. +    memcpy(str,mpc->mpc_productid,12);
  1213. +    str[12]=0;
  1214. +    printk("Product ID: %s ",str);
  1215. +    printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
  1216. +    
  1217. +    /*
  1218. +     *    Now process the configuration blocks.
  1219. +     */
  1220. +     
  1221. +    while(count<mpc->mpc_length)
  1222. +    {
  1223. +        switch(*mpt)
  1224. +        {
  1225. +            case MP_PROCESSOR:
  1226. +            {
  1227. +                struct mpc_config_processor *m=
  1228. +                    (struct mpc_config_processor *)mpt;
  1229. +                if(m->mpc_cpuflag&CPU_ENABLED)
  1230. +                {
  1231. +                    printk("Processor #%d %s APIC version %d\n",
  1232. +                        m->mpc_apicid, 
  1233. +                        mpc_family((m->mpc_cpufeature&
  1234. +                            CPU_FAMILY_MASK)>>8,
  1235. +                            (m->mpc_cpufeature&
  1236. +                                CPU_MODEL_MASK)>>4),
  1237. +                        m->mpc_apicver);
  1238. +                    if(m->mpc_featureflag&(1<<0))
  1239. +                        printk("    Floating point unit present.\n");
  1240. +                    if(m->mpc_featureflag&(1<<7))
  1241. +                        printk("    Machine Exception supported.\n");
  1242. +                    if(m->mpc_featureflag&(1<<8))
  1243. +                        printk("    64 bit compare & exchange supported.\n");
  1244. +                    if(m->mpc_featureflag&(1<<9))
  1245. +                        printk("    Internal APIC present.\n");
  1246. +                    if(m->mpc_cpuflag&CPU_BOOTPROCESSOR)
  1247. +                    {
  1248. +                        printk("    Bootup CPU\n");
  1249. +                        boot_cpu_id=m->mpc_apicid;
  1250. +                        nlong = boot_cpu_id<<24;    /* Dummy 'self' for bootup */
  1251. +                    }
  1252. +                    else    /* Boot CPU already counted */
  1253. +                        num_processors++;
  1254. +                        
  1255. +                    if(m->mpc_apicid>NR_CPUS)
  1256. +                        printk("Processor #%d unused. (Max %d processors).\n",m->mpc_apicid, NR_CPUS);
  1257. +                    else                        
  1258. +                        cpu_present_map|=(1<<m->mpc_apicid);
  1259. +                }
  1260. +                mpt+=sizeof(*m);
  1261. +                count+=sizeof(*m);
  1262. +                break;
  1263. +            }
  1264. +            case MP_BUS:
  1265. +            {
  1266. +                struct mpc_config_bus *m=
  1267. +                    (struct mpc_config_bus *)mpt;
  1268. +                memcpy(str,m->mpc_bustype,6);
  1269. +                str[6]=0;
  1270. +                printk("Bus #%d is %s\n",
  1271. +                    m->mpc_busid,
  1272. +                    str);
  1273. +                mpt+=sizeof(*m);
  1274. +                count+=sizeof(*m);
  1275. +                break; 
  1276. +            }
  1277. +            case MP_IOAPIC:
  1278. +            {
  1279. +                struct mpc_config_ioapic *m=
  1280. +                    (struct mpc_config_ioapic *)mpt;
  1281. +                if(m->mpc_flags&MPC_APIC_USABLE)
  1282. +                {
  1283. +                    apics++;
  1284. +                                    printk("I/O APIC #%d Version %d at 0x%lX.\n",
  1285. +                                        m->mpc_apicid,m->mpc_apicver,
  1286. +                                        m->mpc_apicaddr);
  1287. +                                    io_apic_addr = m->mpc_apicaddr;
  1288. +                            }
  1289. +                                mpt+=sizeof(*m);
  1290. +                                count+=sizeof(*m); 
  1291. +                                break;
  1292. +            }
  1293. +            case MP_INTSRC:
  1294. +            {
  1295. +                struct mpc_config_intsrc *m=
  1296. +                    (struct mpc_config_intsrc *)mpt;
  1297. +                
  1298. +                mpt+=sizeof(*m);
  1299. +                count+=sizeof(*m);
  1300. +                break;
  1301. +            }
  1302. +            case MP_LINTSRC:
  1303. +            {
  1304. +                struct mpc_config_intlocal *m=
  1305. +                    (struct mpc_config_intlocal *)mpt;
  1306. +                mpt+=sizeof(*m);
  1307. +                count+=sizeof(*m);
  1308. +                break;
  1309. +            }
  1310. +        }
  1311. +    }
  1312. +    if(apics>1)
  1313. +        printk("Warning: Multiple APIC's not supported.\n");
  1314. +    return num_processors;                
  1315. +}
  1316. +
  1317. +/*
  1318. + *    Scan the memory blocks for an SMP configuration block.
  1319. + */
  1320. +void smp_scan_config(unsigned long base, unsigned long length)
  1321. +{
  1322. +    unsigned long *bp=(unsigned long *)base;
  1323. +    struct intel_mp_floating *mpf;
  1324. +    num_processors = 1;        /* The boot processor */
  1325. +    
  1326. +/*    printk("Scan SMP from %p for %ld bytes.\n",
  1327. +        bp,length);*/
  1328. +    if(sizeof(*mpf)!=16)
  1329. +        printk("Error: MPF size\n");
  1330. +    
  1331. +    while(length>0)
  1332. +    {
  1333. +        if(*bp==SMP_MAGIC_IDENT)
  1334. +        {
  1335. +            mpf=(struct intel_mp_floating *)bp;
  1336. +            if(mpf->mpf_length==1 && 
  1337. +                !mpf_checksum((unsigned char *)bp,16) &&
  1338. +                mpf->mpf_specification==1)
  1339. +            {
  1340. +                printk("Intel multiprocessing (MPv1.1) available.\n");
  1341. +                if(mpf->mpf_feature2&(1<<7))
  1342. +                    printk("    IMCR and PIC mode supported.\n");
  1343. +                smp_found_config=1;
  1344. +                /*
  1345. +                 *    Now see if we need to read further.
  1346. +                 */
  1347. +                if(mpf->mpf_feature1!=0)
  1348. +                {
  1349. +                    num_processors=2;
  1350. +                    printk("I/O APIC at 0xFEC00000.\n");
  1351. +                    printk("Bus#0 is ");
  1352. +                }
  1353. +                switch(mpf->mpf_feature1)
  1354. +                {
  1355. +                    case 1:
  1356. +                        printk("ISA");
  1357. +                        break;
  1358. +                    case 2:
  1359. +                        printk("EISA with no IRQ8 chaining");
  1360. +                        break;
  1361. +                    case 3:
  1362. +                        printk("EISA");
  1363. +                        break;
  1364. +                    case 4:
  1365. +                        printk("MCA");
  1366. +                        break;
  1367. +                    case 5:
  1368. +                        printk("ISA\nBus#1 is PCI");
  1369. +                        break;
  1370. +                    case 6:
  1371. +                        printk("EISA\nBus #1 is PCI");
  1372. +                        break;
  1373. +                    case 7:
  1374. +                        printk("MCA\nBus #1 is PCI");
  1375. +                        break;
  1376. +                    case 0:
  1377. +                        break;
  1378. +                    default:
  1379. +                        printk("???\nUnknown standard configuration %d\n",
  1380. +                            mpf->mpf_feature1);
  1381. +                        return;
  1382. +                }
  1383. +                if(mpf->mpf_physptr)
  1384. +                    smp_read_mpc((void *)mpf->mpf_physptr);
  1385. +                printk("Processors: %d\n", num_processors);
  1386. +            }
  1387. +        }
  1388. +        bp+=4;
  1389. +        length-=16;
  1390. +    }
  1391. +}
  1392. +
  1393. +/*
  1394. + *    Trampoline 80x86 program as an array.
  1395. + */
  1396. +
  1397. +static unsigned char trampoline_data[]={ 
  1398. +#include  "trampoline.hex"
  1399. +};
  1400. +
  1401. +/*
  1402. + *    Currently trivial. Write the real->protected mode
  1403. + *    bootstrap into the page concerned. The caller
  1404. + *    has made sure its suitably aligned.
  1405. + */
  1406. +static void install_trampoline(unsigned char *mp)
  1407. +{
  1408. +    memcpy(mp,trampoline_data,sizeof(trampoline_data));
  1409. +}
  1410. +
  1411. +/*
  1412. + *    We are called very early to get the low memory for the trampoline/kernel stacks
  1413. + *    This has to be done by mm/init.c to parcel us out nice low memory. We allocate
  1414. + *    the kernel stacks at 4K, 8K, 12K... currently (0-03FF is preserved for SMM and
  1415. + *    other things).
  1416. + */
  1417. +unsigned long smp_alloc_memory(unsigned long mem_base)
  1418. +{
  1419. +    int size=(num_processors-1)*PAGE_SIZE;        /* Number of stacks needed */
  1420. +    /*
  1421. +     *    Our stacks have to be below the 1Mb line, and mem_base on entry
  1422. +     *    is 4K aligned.
  1423. +     */
  1424. +     
  1425. +    if(mem_base+size>=0x9F000)
  1426. +        panic("smp_alloc_memory: Insufficient low memory for kernel stacks.\n");
  1427. +    kstack_base=(void *)mem_base;
  1428. +    mem_base+=size;
  1429. +    kstack_end=(void *)mem_base;
  1430. +    return mem_base;
  1431. +}
  1432. +    
  1433. +/*
  1434. + *    Hand out stacks one at a time.
  1435. + */
  1436. +static void *get_kernel_stack(void)
  1437. +{
  1438. +    void *stack=kstack_base;
  1439. +    if(kstack_base>=kstack_end)
  1440. +        return NULL;
  1441. +    kstack_base+=PAGE_SIZE;
  1442. +    return stack;
  1443. +}
  1444. +
  1445. +
  1446. +/*
  1447. + *    The bootstrap kernel entry code has set these up. Save them for
  1448. + *    a given CPU
  1449. + */
  1450. +void smp_store_cpu_info(int id)
  1451. +{
  1452. +    struct cpuinfo_x86 *c=&cpu_data[id];
  1453. +    c->hard_math=hard_math;            /* Always assumed same currently */
  1454. +    c->x86=x86;
  1455. +    c->x86_model=x86_model;
  1456. +    c->x86_mask=x86_mask;
  1457. +    c->x86_capability=x86_capability;
  1458. +    c->fdiv_bug=fdiv_bug;
  1459. +    c->wp_works_ok=wp_works_ok;        /* Always assumed the same currently */
  1460. +    c->hlt_works_ok=hlt_works_ok;
  1461. +    c->udelay_val=loops_per_sec;
  1462. +    strcpy(c->x86_vendor_id, x86_vendor_id);
  1463. +}
  1464. +
  1465. +/*
  1466. + *    Architecture specific routine called by the kernel just before init is
  1467. + *    fired off. This allows the BP to have everything in order [we hope].
  1468. + *    At the end of this all the AP's will hit the system scheduling and off
  1469. + *    we go. Each AP will load the system gdt's and jump through the kernel
  1470. + *    init into idle(). At this point the scheduler will one day take over 
  1471. + *     and give them jobs to do. smp_callin is a standard routine
  1472. + *    we use to track CPU's as they power up.
  1473. + */
  1474. +
  1475. +void smp_commence(void)
  1476. +{
  1477. +    /*
  1478. +     *    Lets the callin's below out of their loop.
  1479. +     */
  1480. +    smp_commenced=1;
  1481. +}
  1482. +void smp_callin(void)
  1483. +{
  1484. +    int cpuid=GET_APIC_ID(apic_read(APIC_ID));
  1485. +    unsigned long l;
  1486. +    /*
  1487. +     *    Activate our APIC
  1488. +     */
  1489. +     
  1490. +/*    printk("CALLIN %d\n",smp_processor_id());*/
  1491. +     l=apic_read(APIC_SPIV);
  1492. +     l|=(1<<8);        /* Enable */
  1493. +     apic_write(APIC_SPIV,l);
  1494. +     sti();
  1495. +    /*
  1496. +     *    Get our bogomips.
  1497. +     */    
  1498. +    calibrate_delay();
  1499. +    /*
  1500. +     *    Save our processor parameters
  1501. +     */
  1502. +     smp_store_cpu_info(cpuid);
  1503. +    /*
  1504. +     *    Allow the master to continue.
  1505. +     */    
  1506. +    set_bit(cpuid, &cpu_callin_map[0]);
  1507. +    /*
  1508. +     *    Until we are ready for SMP scheduling
  1509. +     */
  1510. +    load_ldt(0);
  1511. +/*    printk("Testing faulting...\n");
  1512. +    *(long *)0=1;         OOPS... */
  1513. +    local_invalidate();
  1514. +    while(!smp_commenced);
  1515. +    local_invalidate();
  1516. +/*    printk("Commenced..\n");*/
  1517. +    
  1518. +    /* This assumes the processor id's are consecutive 0..n-1 -  FIXME */
  1519. +    load_TR(cpuid);
  1520. +/*    while(1);*/
  1521. +}
  1522. +
  1523. +/*
  1524. + *    Cycle through the processors sending pentium IPI's to boot each.
  1525. + */
  1526. +void smp_boot_cpus(void)
  1527. +{
  1528. +    int i=0;
  1529. +    int cpucount=0;
  1530. +    void *stack;
  1531. +    extern unsigned long init_user_stack[];
  1532. +    
  1533. +    /*
  1534. +     *    Map the local APIC into kernel space
  1535. +     */
  1536. +    
  1537. +    apic_reg = vremap(0xFEE00000,4096);
  1538. +    
  1539. +    
  1540. +    if(apic_reg == NULL)
  1541. +        panic("Unable to map local apic.\n");
  1542. +        
  1543. +    /*
  1544. +     *    Now scan the cpu present map and fire up anything we find.
  1545. +     */
  1546. +     
  1547. +     
  1548. +    kernel_stacks[boot_cpu_id]=(void *)init_user_stack;    /* Set up for boot processor first */
  1549. +
  1550. +    smp_store_cpu_info(boot_cpu_id);            /* Final full version of the data */
  1551. +    
  1552. +    active_kernel_processor=boot_cpu_id;
  1553. +        
  1554. +    for(i=0;i<NR_CPUS;i++)
  1555. +    {
  1556. +        if((cpu_present_map&(1<<i)) && i!=boot_cpu_id)        /* Rebooting yourself is a bad move */
  1557. +        {
  1558. +            unsigned long cfg;
  1559. +            int timeout;
  1560. +            
  1561. +            /*
  1562. +             *    We need a kernel stack for each processor.
  1563. +             */
  1564. +            
  1565. +            stack=get_kernel_stack();    /* We allocated these earlier */
  1566. +            if(stack==NULL)
  1567. +                panic("No memory for processor stacks.\n");
  1568. +            kernel_stacks[i]=stack;
  1569. +            install_trampoline(stack);
  1570. +            
  1571. +            printk("Booting processor %d stack %p: ",i,stack);            /* So we set whats up   */
  1572. +                
  1573. +            /*
  1574. +             *    Enable the local APIC
  1575. +             */
  1576. +             
  1577. +            cfg=apic_read(APIC_SPIV);
  1578. +            cfg|=(1<<8);        /* Enable APIC */
  1579. +            apic_write(APIC_SPIV,cfg);
  1580. +            
  1581. +            /*
  1582. +             *    This gunge sends an IPI (Inter Processor Interrupt) to the
  1583. +             *    processor we wish to wake. When the startup IPI is received
  1584. +             *    the target CPU does a real mode jump to the stack base.
  1585. +             */
  1586. +            
  1587. +            cfg=apic_read(APIC_ICR2);
  1588. +            cfg&=0x00FFFFFF;
  1589. +            apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i));            /* Target chip         */
  1590. +            cfg=apic_read(APIC_ICR);
  1591. +            cfg&=~0xFDFFF    ;                            /* Clear bits         */
  1592. +            cfg|=APIC_DEST_FIELD|APIC_DEST_DM_STARTUP|(((unsigned long)stack)>>12);    /* Boot on the stack     */        
  1593. +            apic_write(APIC_ICR, cfg);                        /* Kick the second     */
  1594. +            udelay(10);                                /* Masses of time     */
  1595. +            cfg=apic_read(APIC_ESR);
  1596. +            if(cfg&4)        /* Send accept error */
  1597. +                printk("Processor refused startup request.\n");
  1598. +            else
  1599. +            {
  1600. +                for(timeout=0;timeout<50000;timeout++)
  1601. +                {
  1602. +                    if(cpu_callin_map[0]&(1<<i))
  1603. +                        break;                /* It has booted */
  1604. +                    udelay(100);                /* Wait 5s total for a response */
  1605. +                }
  1606. +                if(cpu_callin_map[0]&(1<<i))
  1607. +                    cpucount++;
  1608. +                else
  1609. +                {
  1610. +                    /*
  1611. +                     *    At this point we should set up a BIOS warm start and try
  1612. +                     *    a RESTART IPI. The 486+82489 MP pair don't support STARTUP IPI's
  1613. +                     */
  1614. +                    if(*((unsigned char *)8192)==0xA5)
  1615. +                        printk("Stuck ??\n");
  1616. +                    else
  1617. +                        printk("Not responding.\n");
  1618. +                    cpu_present_map&=~(1<<i);
  1619. +                }
  1620. +            }
  1621. +        }
  1622. +    }
  1623. +    /*
  1624. +     *    Allow the user to impress friends.
  1625. +     */
  1626. +    if(cpucount==0)
  1627. +        printk("Error: only one processor found.\n");
  1628. +    else
  1629. +    {
  1630. +        printk("Total of %d processors activated.\n", cpucount+1);
  1631. +        smp_activated=1;
  1632. +        smp_num_cpus=cpucount+1;
  1633. +    }
  1634. +}
  1635. +
  1636. +
  1637. +/*
  1638. + *    A non wait message cannot pass data or cpu source info. This current setup
  1639. + *    is only safe because the kernel lock owner is the only person who can send a message.
  1640. + *
  1641. + *    Wrapping this whole block in a spinlock is not the safe answer either. A processor may
  1642. + *    get stuck with irq's off waiting to send a message and thus not replying to the person
  1643. + *    spinning for a reply....
  1644. + *
  1645. + *    In the end invalidate ought to be the NMI and a very very short function (to avoid the old
  1646. + *    IDE disk problems), and other messages sent with IRQ's enabled in a civilised fashion. That
  1647. + *    will also boost performance.
  1648. + */
  1649. +void smp_message_pass(int target, int msg, unsigned long data, int wait)
  1650. +{
  1651. +    unsigned long cfg;
  1652. +    unsigned long target_map;
  1653. +    int p=smp_processor_id();
  1654. +    int irq=0x2d;                                /* IRQ 13 */
  1655. +    int ct=0;
  1656. +    static volatile int message_cpu = NO_PROC_ID;
  1657. +
  1658. +    /*
  1659. +     *    During boot up send no messages
  1660. +     */
  1661. +     
  1662. +    if(!smp_activated)
  1663. +        return;
  1664. +        
  1665. +    
  1666. +    /*
  1667. +     *    Skip the reschedule if we are waiting to clear a
  1668. +     *    message at this time. The reschedule cannot wait
  1669. +     *    but is not critical.
  1670. +     */
  1671. +    
  1672. +    if(msg==MSG_RESCHEDULE)                            /* Reschedules we do via trap 0x30 */
  1673. +    {
  1674. +        irq=0x30;
  1675. +        if(smp_cpu_in_msg[p])
  1676. +            return;
  1677. +    }
  1678. +
  1679. +    /*
  1680. +     *    Sanity check we don't re-enter this across CPU's. Only the kernel
  1681. +     *    lock holder may send messages. For a STOP_CPU we are bringing the
  1682. +     *    entire box to the fastest halt we can.. 
  1683. +     */
  1684. +     
  1685. +    if(message_cpu!=NO_PROC_ID && msg!=MSG_STOP_CPU)
  1686. +    {
  1687. +        panic("CPU #%d: Message pass %d but pass in progress by %d of %d\n",
  1688. +            smp_processor_id(),msg,message_cpu, smp_msg_id);
  1689. +    }
  1690. +    message_cpu=smp_processor_id();
  1691. +    
  1692. +
  1693. +    /*
  1694. +     *    We are busy
  1695. +     */
  1696. +         
  1697. +    smp_cpu_in_msg[p]++;
  1698. +    
  1699. +    /*
  1700. +     *    Reschedule is currently special
  1701. +     */
  1702. +     
  1703. +    if(msg!=MSG_RESCHEDULE)
  1704. +    {
  1705. +        smp_src_cpu=p;
  1706. +        smp_msg_id=msg;
  1707. +        smp_msg_data=data;
  1708. +    }
  1709. +    
  1710. +/*    printk("SMP message pass #%d to %d of %d\n",
  1711. +        p, msg, target);*/
  1712. +    
  1713. +    /*
  1714. +     *    Wait for the APIC to become ready - this should never occur. Its
  1715. +     *    a debugging check really.
  1716. +     */
  1717. +     
  1718. +    while(ct<1000)
  1719. +    {
  1720. +        cfg=apic_read(APIC_ICR);
  1721. +        if(!(cfg&(1<<12)))
  1722. +            break;
  1723. +        ct++;
  1724. +        udelay(10);
  1725. +    }
  1726. +    
  1727. +    /*
  1728. +     *    Just pray... there is nothing more we can do
  1729. +     */
  1730. +     
  1731. +    if(ct==1000)
  1732. +        printk("CPU #%d: previous IPI still not cleared after 10mS", smp_processor_id());
  1733. +        
  1734. +    /*
  1735. +     *    Program the APIC to deliver the IPI
  1736. +     */
  1737. +     
  1738. +    cfg=apic_read(APIC_ICR2);
  1739. +    cfg&=0x00FFFFFF;
  1740. +    apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(target));            /* Target chip             */
  1741. +    cfg=apic_read(APIC_ICR);
  1742. +    cfg&=~0xFDFFF;                                /* Clear bits             */
  1743. +    cfg|=APIC_DEST_FIELD|APIC_DEST_DM_FIXED|irq;                /* Send an IRQ 13        */        
  1744. +
  1745. +    /*
  1746. +     *    Set the target requirement
  1747. +     */
  1748. +     
  1749. +    if(target==MSG_ALL_BUT_SELF)
  1750. +    {
  1751. +        cfg|=APIC_DEST_ALLBUT;
  1752. +        target_map=cpu_present_map;
  1753. +        cpu_callin_map[0]=(1<<smp_src_cpu);
  1754. +    }
  1755. +    else if(target==MSG_ALL)
  1756. +    {
  1757. +        cfg|=APIC_DEST_ALLINC;
  1758. +        target_map=cpu_present_map;
  1759. +        cpu_callin_map[0]=0;
  1760. +    }
  1761. +    else
  1762. +    {
  1763. +        target_map=(1<<target);
  1764. +        cpu_callin_map[0]=0;
  1765. +    }
  1766. +        
  1767. +    /*
  1768. +     *    Send the IPI. The write to APIC_ICR fires this off.
  1769. +     */
  1770. +     
  1771. +    apic_write(APIC_ICR, cfg);    
  1772. +    
  1773. +    /*
  1774. +     *    Spin waiting for completion
  1775. +     */
  1776. +     
  1777. +    switch(wait)
  1778. +    {
  1779. +        case 1:
  1780. +            while(cpu_callin_map[0]!=target_map);        /* Spin on the pass        */
  1781. +            break;
  1782. +        case 2:
  1783. +            while(smp_invalidate_needed);            /* Wait for invalidate map to clear */
  1784. +            break;
  1785. +    }
  1786. +    
  1787. +    /*
  1788. +     *    Record our completion
  1789. +     */
  1790. +     
  1791. +    smp_cpu_in_msg[p]--;
  1792. +    message_cpu=NO_PROC_ID;
  1793. +}
  1794. +
  1795. +/*
  1796. + *    This is fraught with deadlocks. Linus does an invalidate at a whim
  1797. + *    even with IRQ's off. We have to avoid a pair of crossing invalidates
  1798. + *    or we are doomed.  See the notes about smp_message_pass.
  1799. + */
  1800. +void smp_invalidate(void)
  1801. +{
  1802. +    unsigned long flags;
  1803. +    if(smp_activated && smp_processor_id()!=active_kernel_processor)
  1804. +        panic("CPU #%d:Attempted invalidate IPI when not AKP(=%d)\n",smp_processor_id(),active_kernel_processor);
  1805. +/*    printk("SMI-");*/
  1806. +    
  1807. +    /*
  1808. +     *    The assignment is safe because its volatile so the compiler cannot reorder it,
  1809. +     *    because the i586 has strict memory ordering and because only the kernel lock holder
  1810. +     *    may issue an invalidate. If you break any one of those three change this to an atomic
  1811. +     *    bus locked or.
  1812. +     */
  1813. +    
  1814. +    smp_invalidate_needed=cpu_present_map&~(1<<smp_processor_id());
  1815. +    
  1816. +    /*
  1817. +     *    Processors spinning on the lock will see this IRQ late. The smp_invalidate_needed map will
  1818. +     *    ensure they dont do a spurious invalidate or miss one.
  1819. +     */
  1820. +     
  1821. +    save_flags(flags);
  1822. +    cli();
  1823. +    smp_message_pass(MSG_ALL_BUT_SELF, MSG_INVALIDATE_TLB, 0L, 2);
  1824. +    
  1825. +    /*
  1826. +     *    Flush the local TLB
  1827. +     */
  1828. +     
  1829. +    local_invalidate();
  1830. +    
  1831. +    restore_flags(flags);
  1832. +    
  1833. +    /*
  1834. +     *    Completed.
  1835. +     */
  1836. +     
  1837. +/*    printk("SMID\n");*/
  1838. +}
  1839. +
  1840. +/*    
  1841. + *    Reschedule call back
  1842. + */
  1843. +
  1844. +void smp_reschedule_irq(int cpl, struct pt_regs *regs)
  1845. +{
  1846. +    static int ct=0;
  1847. +    if(ct==0)
  1848. +    {
  1849. +        printk("Beginning scheduling on CPU#%d\n",smp_processor_id());
  1850. +        ct=1;
  1851. +    }
  1852. +    
  1853. +    if(smp_processor_id()!=active_kernel_processor)
  1854. +        panic("SMP Reschedule on CPU #%d, but #%d is active.\n",
  1855. +            smp_processor_id(), active_kernel_processor);
  1856. +    /*
  1857. +     *    Update resource usage on the slave timer tick.
  1858. +     */
  1859. +            
  1860. +    if (user_mode(regs)) 
  1861. +    {
  1862. +        current->utime++;
  1863. +        if (current->pid) 
  1864. +        {
  1865. +            if (current->priority < 15)
  1866. +                kstat.cpu_nice++;
  1867. +            else
  1868. +                kstat.cpu_user++;
  1869. +        }
  1870. +        /* Update ITIMER_VIRT for current task if not in a system call */
  1871. +        if (current->it_virt_value && !(--current->it_virt_value)) {
  1872. +            current->it_virt_value = current->it_virt_incr;
  1873. +            send_sig(SIGVTALRM,current,1);
  1874. +        }
  1875. +    } else {
  1876. +        current->stime++;
  1877. +        if(current->pid)
  1878. +            kstat.cpu_system++;
  1879. +#ifdef CONFIG_PROFILE
  1880. +        if (prof_buffer && current->pid) {
  1881. +            extern int _stext;
  1882. +            unsigned long eip = regs->eip - (unsigned long) &_stext;
  1883. +            eip >>= CONFIG_PROFILE_SHIFT;
  1884. +            if (eip < prof_len)
  1885. +                prof_buffer[eip]++;
  1886. +        }
  1887. +#endif
  1888. +    }
  1889. +    /*
  1890. +     * check the cpu time limit on the process.
  1891. +     */
  1892. +    if ((current->rlim[RLIMIT_CPU].rlim_max != RLIM_INFINITY) &&
  1893. +        (((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_max))
  1894. +        send_sig(SIGKILL, current, 1);
  1895. +    if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
  1896. +        (((current->stime + current->utime) % HZ) == 0)) {
  1897. +        unsigned long psecs = (current->stime + current->utime) / HZ;
  1898. +        /* send when equal */
  1899. +        if (psecs == current->rlim[RLIMIT_CPU].rlim_cur)
  1900. +            send_sig(SIGXCPU, current, 1);
  1901. +        /* and every five seconds thereafter. */
  1902. +        else if ((psecs > current->rlim[RLIMIT_CPU].rlim_cur) &&
  1903. +                ((psecs - current->rlim[RLIMIT_CPU].rlim_cur) % 5) == 0)
  1904. +            send_sig(SIGXCPU, current, 1);
  1905. +    }
  1906. +
  1907. +    /* Update ITIMER_PROF for the current task */
  1908. +    if (current->it_prof_value && !(--current->it_prof_value)) {
  1909. +        current->it_prof_value = current->it_prof_incr;
  1910. +        send_sig(SIGPROF,current,1);
  1911. +    }
  1912. +
  1913. +
  1914. +    /*
  1915. +     *    Don't reschedule if we are in an interrupt...
  1916. +     *    [This is test code and not needed in the end]
  1917. +     */
  1918. +     
  1919. +/*    if(intr_count==1)
  1920. +    {*/
  1921. +
  1922. +        /*
  1923. +         *    See if the slave processors need a schedule.
  1924. +         */
  1925. +
  1926. +        if ( 0 > --current->counter || current->pid == 0) 
  1927. +        {
  1928. +            current->counter = 0;
  1929. +            need_resched=1;
  1930. +        }
  1931. +/*    }*/
  1932. +
  1933. +    /*
  1934. +     *    Clear the IPI
  1935. +     */
  1936. +    apic_read(APIC_SPIV);        /* Dummy read */
  1937. +    apic_write(APIC_EOI, 0);    /* Docs say use 0 for future compatibility */
  1938. +}    
  1939. +
  1940. +/*
  1941. + *    Message call back.
  1942. + */
  1943. +void smp_message_irq(int cpl, struct pt_regs *regs)
  1944. +{
  1945. +    static int n=0;
  1946. +    int i=smp_processor_id();
  1947. +/*    if(n++<NR_CPUS)
  1948. +        printk("IPI %d->%d(%d,%ld)\n",smp_src_cpu,i,smp_msg_id,smp_msg_data);*/
  1949. +    switch(smp_msg_id)
  1950. +    {
  1951. +        case 0:    /* IRQ 13 testing - boring */
  1952. +            return;
  1953. +            
  1954. +        /*
  1955. +         *    A TLB flush is needed.
  1956. +         */
  1957. +         
  1958. +        case MSG_INVALIDATE_TLB:
  1959. +            if(clear_bit(i,&smp_invalidate_needed))
  1960. +                local_invalidate();
  1961. +            set_bit(i, &cpu_callin_map[0]);
  1962. +            cpu_callin_map[0]|=1<<smp_processor_id();
  1963. +            break;
  1964. +            
  1965. +        /*
  1966. +         *    Halt other CPU's for a panic or reboot
  1967. +         */
  1968. +        case MSG_STOP_CPU:
  1969. +            while(1)
  1970. +            {
  1971. +                if(cpu_data[smp_processor_id()].hlt_works_ok)
  1972. +                    __asm__("hlt");
  1973. +            }
  1974. +        default:
  1975. +            printk("CPU #%d sent invalid cross CPU message to CPU #%d: %X(%lX).\n",
  1976. +                smp_src_cpu,smp_processor_id(),smp_msg_id,smp_msg_data);
  1977. +            break;
  1978. +    }
  1979. +    /*
  1980. +     *    Clear the IPI, so we can receive future IPI's
  1981. +     */
  1982. +     
  1983. +    apic_read(APIC_SPIV);        /* Dummy read */
  1984. +    apic_write(APIC_EOI, 0);    /* Docs say use 0 for future compatibility */
  1985. +}
  1986. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
  1987. --- v1.3.30/linux/arch/i386/kernel/time.c    Wed Sep 27 15:59:56 1995
  1988. +++ linux/arch/i386/kernel/time.c    Mon Oct  2 17:41:24 1995
  1989. @@ -26,104 +26,58 @@
  1990.  
  1991.  #define TIMER_IRQ 0
  1992.  
  1993. -static int set_rtc_mmss(unsigned long);
  1994. +/* Cycle counter value at the previous timer interrupt.. */
  1995. +static unsigned long long last_timer_cc = 0;
  1996. +static unsigned long long init_timer_cc = 0;
  1997.  
  1998. -/*
  1999. - * timer_interrupt() needs to keep up the real-time clock,
  2000. - * as well as call the "do_timer()" routine every clocktick
  2001. - */
  2002. -static void timer_interrupt(int irq, struct pt_regs * regs)
  2003. +static unsigned long do_fast_gettimeoffset(void)
  2004.  {
  2005. -    /* last time the cmos clock got updated */
  2006. -    static long last_rtc_update=0;
  2007. -
  2008. -    do_timer(regs);
  2009. +    unsigned long time_low, time_high;
  2010. +    unsigned long quotient, remainder;
  2011.  
  2012. +    /* Get last timer tick in absolute kernel time */
  2013. +    __asm__("subl %2,%0\n\t"
  2014. +        "sbbl %3,%1"
  2015. +        :"=r" (time_low), "=r" (time_high)
  2016. +        :"m" (*(0+(long *)&init_timer_cc)),
  2017. +         "m" (*(1+(long *)&init_timer_cc)),
  2018. +         "0" (*(0+(long *)&last_timer_cc)),
  2019. +         "1" (*(1+(long *)&last_timer_cc)));
  2020.      /*
  2021. -     * If we have an externally synchronized Linux clock, then update
  2022. -     * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
  2023. -     * called as close as possible to 500 ms before the new second starts.
  2024. +     * Divide the 64-bit time with the 32-bit jiffy counter,
  2025. +     * getting the quotient in clocks.
  2026. +     *
  2027. +     * Giving quotient = "average internal clocks per jiffy"
  2028.       */
  2029. -    if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
  2030. -        xtime.tv_usec > 500000 - (tick >> 1) &&
  2031. -        xtime.tv_usec < 500000 + (tick >> 1))
  2032. -      if (set_rtc_mmss(xtime.tv_sec) == 0)
  2033. -        last_rtc_update = xtime.tv_sec;
  2034. -      else
  2035. -        last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
  2036. -}
  2037. +    __asm__("divl %2"
  2038. +        :"=a" (quotient), "=d" (remainder)
  2039. +        :"r" (jiffies),
  2040. +         "0" (time_low), "1" (time_high));
  2041. +
  2042. +    /* Read the time counter */
  2043. +    __asm__(".byte 0x0f,0x31"
  2044. +        :"=a" (time_low), "=d" (time_high));
  2045.  
  2046. -/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  2047. - * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  2048. - * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  2049. - *
  2050. - * [For the Julian calendar (which was used in Russia before 1917,
  2051. - * Britain & colonies before 1752, anywhere else before 1582,
  2052. - * and is still in use by some communities) leave out the
  2053. - * -year/100+year/400 terms, and add 10.]
  2054. - *
  2055. - * This algorithm was first published by Gauss (I think).
  2056. - *
  2057. - * WARNING: this function will overflow on 2106-02-07 06:28:16 on
  2058. - * machines were long is 32-bit! (However, as time_t is signed, we
  2059. - * will already get problems at other places on 2038-01-19 03:14:08)
  2060. - */
  2061. -static inline unsigned long mktime(unsigned int year, unsigned int mon,
  2062. -    unsigned int day, unsigned int hour,
  2063. -    unsigned int min, unsigned int sec)
  2064. -{
  2065. -    if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
  2066. -        mon += 12;    /* Puts Feb last since it has leap day */
  2067. -        year -= 1;
  2068. -    }
  2069. -    return (((
  2070. -        (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
  2071. -          year*365 - 719499
  2072. -        )*24 + hour /* now have hours */
  2073. -       )*60 + min /* now have minutes */
  2074. -      )*60 + sec; /* finally seconds */
  2075. -}
  2076. +    /* .. relative to previous jiffy (32 bits is enough) */
  2077. +    time_low -= (unsigned long) last_timer_cc;
  2078.  
  2079. -void time_init(void)
  2080. -{
  2081. -    unsigned int year, mon, day, hour, min, sec;
  2082. -    int i;
  2083. +    /*
  2084. +     * Time offset = (1000000/HZ * remainder) / quotient.
  2085. +     */
  2086. +    __asm__("mull %1\n\t"
  2087. +        "divl %2"
  2088. +        :"=a" (quotient), "=d" (remainder)
  2089. +        :"r" (quotient),
  2090. +         "0" (time_low), "1" (1000000/HZ));
  2091.  
  2092. -    /* The Linux interpretation of the CMOS clock register contents:
  2093. -     * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
  2094. -     * RTC registers show the second which has precisely just started.
  2095. -     * Let's hope other operating systems interpret the RTC the same way.
  2096. +    /*
  2097. +     * Due to rounding errors (and jiffies inconsistencies),
  2098. +     * we need to check the result so that we'll get a timer
  2099. +     * that is monotonous.
  2100.       */
  2101. -    /* read RTC exactly on falling edge of update flag */
  2102. -    for (i = 0 ; i < 1000000 ; i++)    /* may take up to 1 second... */
  2103. -        if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
  2104. -            break;
  2105. -    for (i = 0 ; i < 1000000 ; i++)    /* must try at least 2.228 ms */
  2106. -        if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
  2107. -            break;
  2108. -    do { /* Isn't this overkill ? UIP above should guarantee consistency */
  2109. -        sec = CMOS_READ(RTC_SECONDS);
  2110. -        min = CMOS_READ(RTC_MINUTES);
  2111. -        hour = CMOS_READ(RTC_HOURS);
  2112. -        day = CMOS_READ(RTC_DAY_OF_MONTH);
  2113. -        mon = CMOS_READ(RTC_MONTH);
  2114. -        year = CMOS_READ(RTC_YEAR);
  2115. -    } while (sec != CMOS_READ(RTC_SECONDS));
  2116. -    if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  2117. -      {
  2118. -        BCD_TO_BIN(sec);
  2119. -        BCD_TO_BIN(min);
  2120. -        BCD_TO_BIN(hour);
  2121. -        BCD_TO_BIN(day);
  2122. -        BCD_TO_BIN(mon);
  2123. -        BCD_TO_BIN(year);
  2124. -      }
  2125. -    if ((year += 1900) < 1970)
  2126. -        year += 100;
  2127. -    xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
  2128. -    xtime.tv_usec = 0;
  2129. -    if (request_irq(TIMER_IRQ, timer_interrupt, 0, "timer") != 0)
  2130. -        panic("Could not allocate timer IRQ!");
  2131. +    if (quotient >= 1000000/HZ)
  2132. +        quotient = 1000000/HZ-1;
  2133. +    return quotient;
  2134.  }
  2135.  
  2136.  /* This function must be called with interrupts disabled 
  2137. @@ -160,7 +114,7 @@
  2138.  
  2139.  #define TICK_SIZE tick
  2140.  
  2141. -static inline unsigned long do_gettimeoffset(void)
  2142. +static unsigned long do_slow_gettimeoffset(void)
  2143.  {
  2144.      int count;
  2145.      unsigned long offset = 0;
  2146. @@ -181,6 +135,8 @@
  2147.      return offset + count;
  2148.  }
  2149.  
  2150. +static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
  2151. +
  2152.  /*
  2153.   * This version of gettimeofday has near microsecond resolution.
  2154.   */
  2155. @@ -279,4 +235,134 @@
  2156.      CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
  2157.  
  2158.      return retval;
  2159. +}
  2160. +
  2161. +/* last time the cmos clock got updated */
  2162. +static long last_rtc_update = 0;
  2163. +
  2164. +/*
  2165. + * timer_interrupt() needs to keep up the real-time clock,
  2166. + * as well as call the "do_timer()" routine every clocktick
  2167. + */
  2168. +static inline void timer_interrupt(int irq, struct pt_regs * regs)
  2169. +{
  2170. +    do_timer(regs);
  2171. +
  2172. +    /*
  2173. +     * If we have an externally synchronized Linux clock, then update
  2174. +     * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
  2175. +     * called as close as possible to 500 ms before the new second starts.
  2176. +     */
  2177. +    if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
  2178. +        xtime.tv_usec > 500000 - (tick >> 1) &&
  2179. +        xtime.tv_usec < 500000 + (tick >> 1))
  2180. +      if (set_rtc_mmss(xtime.tv_sec) == 0)
  2181. +        last_rtc_update = xtime.tv_sec;
  2182. +      else
  2183. +        last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
  2184. +    /* As we return to user mode fire off the other CPU schedulers.. this is 
  2185. +       basically because we don't yet share IRQ's around. This message is
  2186. +       rigged to be safe on the 386 - basically its a hack, so don't look
  2187. +       closely for now.. */
  2188. +    smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); 
  2189. +        
  2190. +}
  2191. +
  2192. +/*
  2193. + * This is the same as the above, except we _also_ save the current
  2194. + * cycle counter value at the time of the timer interrupt, so that
  2195. + * we later on can estimate the time of day more exactly.
  2196. + */
  2197. +static void pentium_timer_interrupt(int irq, struct pt_regs * regs)
  2198. +{
  2199. +    /* read Pentium cycle counter */
  2200. +    __asm__(".byte 0x0f,0x31"
  2201. +        :"=a" (((unsigned long *) &last_timer_cc)[0]),
  2202. +         "=d" (((unsigned long *) &last_timer_cc)[1]));
  2203. +    timer_interrupt(irq, regs);
  2204. +}
  2205. +
  2206. +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  2207. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  2208. + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  2209. + *
  2210. + * [For the Julian calendar (which was used in Russia before 1917,
  2211. + * Britain & colonies before 1752, anywhere else before 1582,
  2212. + * and is still in use by some communities) leave out the
  2213. + * -year/100+year/400 terms, and add 10.]
  2214. + *
  2215. + * This algorithm was first published by Gauss (I think).
  2216. + *
  2217. + * WARNING: this function will overflow on 2106-02-07 06:28:16 on
  2218. + * machines were long is 32-bit! (However, as time_t is signed, we
  2219. + * will already get problems at other places on 2038-01-19 03:14:08)
  2220. + */
  2221. +static inline unsigned long mktime(unsigned int year, unsigned int mon,
  2222. +    unsigned int day, unsigned int hour,
  2223. +    unsigned int min, unsigned int sec)
  2224. +{
  2225. +    if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
  2226. +        mon += 12;    /* Puts Feb last since it has leap day */
  2227. +        year -= 1;
  2228. +    }
  2229. +    return (((
  2230. +        (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
  2231. +          year*365 - 719499
  2232. +        )*24 + hour /* now have hours */
  2233. +       )*60 + min /* now have minutes */
  2234. +      )*60 + sec; /* finally seconds */
  2235. +}
  2236. +
  2237. +void time_init(void)
  2238. +{
  2239. +    void (*irq_handler)(int, struct pt_regs *);
  2240. +    unsigned int year, mon, day, hour, min, sec;
  2241. +    int i;
  2242. +
  2243. +    /* The Linux interpretation of the CMOS clock register contents:
  2244. +     * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
  2245. +     * RTC registers show the second which has precisely just started.
  2246. +     * Let's hope other operating systems interpret the RTC the same way.
  2247. +     */
  2248. +    /* read RTC exactly on falling edge of update flag */
  2249. +    for (i = 0 ; i < 1000000 ; i++)    /* may take up to 1 second... */
  2250. +        if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
  2251. +            break;
  2252. +    for (i = 0 ; i < 1000000 ; i++)    /* must try at least 2.228 ms */
  2253. +        if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
  2254. +            break;
  2255. +    do { /* Isn't this overkill ? UIP above should guarantee consistency */
  2256. +        sec = CMOS_READ(RTC_SECONDS);
  2257. +        min = CMOS_READ(RTC_MINUTES);
  2258. +        hour = CMOS_READ(RTC_HOURS);
  2259. +        day = CMOS_READ(RTC_DAY_OF_MONTH);
  2260. +        mon = CMOS_READ(RTC_MONTH);
  2261. +        year = CMOS_READ(RTC_YEAR);
  2262. +    } while (sec != CMOS_READ(RTC_SECONDS));
  2263. +    if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  2264. +      {
  2265. +        BCD_TO_BIN(sec);
  2266. +        BCD_TO_BIN(min);
  2267. +        BCD_TO_BIN(hour);
  2268. +        BCD_TO_BIN(day);
  2269. +        BCD_TO_BIN(mon);
  2270. +        BCD_TO_BIN(year);
  2271. +      }
  2272. +    if ((year += 1900) < 1970)
  2273. +        year += 100;
  2274. +    xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
  2275. +    xtime.tv_usec = 0;
  2276. +
  2277. +    /* If we have the CPU hardware time counters, use them */
  2278. +    irq_handler = timer_interrupt;    
  2279. +    if (x86_capability & 16) {
  2280. +        irq_handler = pentium_timer_interrupt;
  2281. +        do_gettimeoffset = do_fast_gettimeoffset;
  2282. +        /* read Pentium cycle counter */
  2283. +        __asm__(".byte 0x0f,0x31"
  2284. +            :"=a" (((unsigned long *) &init_timer_cc)[0]),
  2285. +             "=d" (((unsigned long *) &init_timer_cc)[1]));
  2286. +    }
  2287. +    if (request_irq(TIMER_IRQ, irq_handler, 0, "timer") != 0)
  2288. +        panic("Could not allocate timer IRQ!");
  2289.  }
  2290. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/trampoline.S linux/arch/i386/kernel/trampoline.S
  2291. --- v1.3.30/linux/arch/i386/kernel/trampoline.S    Thu Jan  1 02:00:00 1970
  2292. +++ linux/arch/i386/kernel/trampoline.S    Mon Oct  2 14:25:10 1995
  2293. @@ -0,0 +1,75 @@
  2294. +!
  2295. +!    Trampoline.S    Derived from Setup.S by Linus Torvalds
  2296. +!
  2297. +!    Entry: CS:IP point to the start of our code, we are 
  2298. +!    in real mode with no stack, but the rest of the 
  2299. +!    trampoline page to make our stack and everything else
  2300. +!    is a mystery.
  2301. +!
  2302. +!    In fact we don't actually need a stack so we don't
  2303. +!    set one up.
  2304. +!
  2305. +!    We jump into the boot/compressed/head.S code. So you'd
  2306. +!    better be running a compressed kernel image or you
  2307. +!    won't get very far.
  2308. +!
  2309. +#define __ASSEMBLY__
  2310. +#include <linux/config.h>
  2311. +#include <asm/segment.h>
  2312. +
  2313. +.text
  2314. +    extrn startup32
  2315. +
  2316. +entry start
  2317. +start:
  2318. +!    nop
  2319. +!    jmp start    !     Test
  2320. +    mov ax,cs    !    Code and data in the same place
  2321. +    mov ds,ax    !
  2322. +    mov cx,ax    !    Pass stack info to the 32bit boot
  2323. +    add cx,cx
  2324. +    add cx,cx
  2325. +    add cx,cx
  2326. +    add cx,cx    !    Segment -> Offset
  2327. +    add cx, #4096   !    End of page is wanted
  2328. +    mov     bx,#1    !    Flag an SMP trampoline
  2329. +    cli        !    We should be safe anyway
  2330. +
  2331. +    lidt    idt_48    !    load idt with 0,0
  2332. +    lgdt    gdt_48    !    load gdt with whatever is appropriate
  2333. +
  2334. +    xor    ax,ax    
  2335. +    inc    ax    !    protected mode (PE) bit
  2336. +    lmsw    ax    !    Into protected mode
  2337. +    jmp    flush_instr
  2338. +flush_instr:
  2339. +    jmpi    8192+startup32,KERNEL_CS    !    Jump to the 32bit trampoline code
  2340. +!    jmpi    0x100000,KERNEL_CS        !    Jump into the 32bit startup
  2341. +!    .byte   0x66,0x67            !    32bit
  2342. +!    .byte    0xea,0x00,0x00,0x10,0x00,0x10,0x00    !jmpi    .0x100000,KERNEL_CS
  2343. +
  2344. +gdt:
  2345. +    .word    0,0,0,0        ! dummy
  2346. +
  2347. +    .word    0,0,0,0        ! unused
  2348. +
  2349. +    .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
  2350. +    .word    0x0000        ! base address=0
  2351. +    .word    0x9A00        ! code read/exec
  2352. +    .word    0x00C0        ! granularity=4096, 386
  2353. +
  2354. +    .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
  2355. +    .word    0x0000        ! base address=0
  2356. +    .word    0x9200        ! data read/write
  2357. +    .word    0x00C0        ! granularity=4096, 386
  2358. +
  2359. +idt_48:
  2360. +    .word    0            ! idt limit=0
  2361. +    .word    0,0            ! idt base=0L
  2362. +
  2363. +gdt_48:
  2364. +    .word    0x800        ! gdt limit=2048, 256 GDT entries
  2365. +    .word    8192+gdt,0x0    ! gdt base = 8192+gdt (first SMP CPU)
  2366. +                ! we load the others with the first table
  2367. +                ! saves rewriting gdt_48 for each
  2368. +
  2369. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/trampoline32.S linux/arch/i386/kernel/trampoline32.S
  2370. --- v1.3.30/linux/arch/i386/kernel/trampoline32.S    Thu Jan  1 02:00:00 1970
  2371. +++ linux/arch/i386/kernel/trampoline32.S    Mon Oct  2 14:25:10 1995
  2372. @@ -0,0 +1,21 @@
  2373. +!
  2374. +!    32bit side of the trampoline code
  2375. +!
  2376. +#define __ASSEMBLY__
  2377. +#include <linux/config.h>
  2378. +#include <asm/segment.h>
  2379. +!
  2380. +!
  2381. +!    Anything but a relative address here will be wrong by 8K...
  2382. +!
  2383. +    .globl startup32
  2384. +.text
  2385. +startup32:
  2386. +!    Run the kernel
  2387. +    mov    eax,#KERNEL_DS
  2388. +    mov    ds,ax
  2389. +    mov    eax,#0xA5A5A5A5
  2390. +    mov    [8192],eax
  2391. +    jmpi    0x100000,KERNEL_CS
  2392. +l1:
  2393. +    .byte    0xEA,0x00,0x00,0x10,0x00,0x10,0x00
  2394. diff -u --recursive --new-file v1.3.30/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
  2395. --- v1.3.30/linux/arch/i386/kernel/traps.c    Wed Aug  2 13:20:58 1995
  2396. +++ linux/arch/i386/kernel/traps.c    Mon Oct  2 14:25:10 1995
  2397. @@ -10,6 +10,7 @@
  2398.   * to mainly kill the offending process (probably by giving it a signal,
  2399.   * but possibly by killing it outright if necessary).
  2400.   */
  2401. +#include <linux/config.h>
  2402.  #include <linux/head.h>
  2403.  #include <linux/sched.h>
  2404.  #include <linux/kernel.h>
  2405. @@ -111,6 +112,7 @@
  2406.      }
  2407.      console_verbose();
  2408.      printk("%s: %04lx\n", str, err & 0xffff);
  2409. +    printk("CPU:    %d\n", smp_processor_id());
  2410.      printk("EIP:    %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
  2411.      printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
  2412.          regs->eax, regs->ebx, regs->ecx, regs->edx);
  2413. @@ -190,11 +192,15 @@
  2414.  
  2415.  asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
  2416.  {
  2417. +#ifdef CONFIG_SMP_NMI_INVAL
  2418. +    smp_invalidate_rcv();
  2419. +#else
  2420.  #ifndef CONFIG_IGNORE_NMI
  2421.      printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
  2422.      printk("You probably have a hardware problem with your RAM chips or a\n");
  2423.      printk("power saving mode enabled.\n");
  2424.  #endif    
  2425. +#endif
  2426.  }
  2427.  
  2428.  asmlinkage void do_debug(struct pt_regs * regs, long error_code)
  2429. @@ -236,7 +242,19 @@
  2430.  void math_error(void)
  2431.  {
  2432.      struct i387_hard_struct * env;
  2433. -
  2434. +#ifdef CONFIG_SMP
  2435. +    env=¤t->tss.i387.hard;
  2436. +    send_sig(SIGFPE, current, 1);
  2437. +    /*
  2438. +     *    Save the info for the exception handler
  2439. +     */
  2440. +    __asm__ __volatile__("fnsave %0":"=m" (*env));
  2441. +    current->flags&=~PF_USEDFPU;
  2442. +    /*
  2443. +     *    Cause a trap if they use the FPU again.
  2444. +     */
  2445. +    stts();
  2446. +#else
  2447.      clts();
  2448.      if (!last_task_used_math) {
  2449.          __asm__("fnclex");
  2450. @@ -253,6 +271,7 @@
  2451.      env->fos = env->twd;
  2452.      env->swd &= 0xffff3800;
  2453.      env->twd = 0xffffffff;
  2454. +#endif    
  2455.  }
  2456.  
  2457.  asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
  2458. @@ -270,6 +289,30 @@
  2459.   */
  2460.  asmlinkage void math_state_restore(void)
  2461.  {
  2462. +#ifdef CONFIG_SMP
  2463. +/*
  2464. + *    SMP is actually simpler than uniprocessor for once. Because
  2465. + *    we can't pull the delayed FPU switching trick Linus does
  2466. + *    we simply have to do the restore each context switch and
  2467. + *    set the flag. switch_to() will always save the state in
  2468. + *    case we swap processors. We also don't use the coprocessor
  2469. + *    timer - IRQ 13 mode isnt used with SMP machines (thank god).
  2470. + *
  2471. + *    If this actually works it will be a miracle however
  2472. + */
  2473. +    __asm__ __volatile__("clts");        /* Allow maths ops (or we recurse) */
  2474. +    if(current->used_math)
  2475. +        __asm__("frstor %0": :"m" (current->tss.i387));
  2476. +    else
  2477. +    {
  2478. +        /*
  2479. +         *    Our first FPU usage, clean the chip.
  2480. +         */
  2481. +        __asm__("fninit");
  2482. +        current->used_math = 1;
  2483. +    }
  2484. +    current->flags|=PF_USEDFPU;        /* So we fnsave on switch_to() */
  2485. +#else
  2486.      __asm__ __volatile__("clts");
  2487.      if (last_task_used_math == current)
  2488.          return;
  2489. @@ -287,6 +330,7 @@
  2490.          current->used_math=1;
  2491.      }
  2492.      timer_active &= ~(1<<COPRO_TIMER);
  2493. +#endif    
  2494.  }
  2495.  
  2496.  #ifndef CONFIG_MATH_EMULATION
  2497. @@ -305,7 +349,15 @@
  2498.  {
  2499.      int i;
  2500.      struct desc_struct * p;
  2501. -
  2502. +    static int smptrap=0;
  2503. +    
  2504. +    if(smptrap)
  2505. +    {
  2506. +        __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
  2507. +        load_ldt(0);
  2508. +        return;
  2509. +    }
  2510. +    smptrap++;
  2511.      if (strncmp((char*)0x0FFFD9, "EISA", 4) == 0)
  2512.          EISA_bus = 1;
  2513.      set_call_gate(&default_ldt,lcall7);
  2514. diff -u --recursive --new-file v1.3.30/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
  2515. --- v1.3.30/linux/arch/i386/mm/init.c    Mon Sep 25 12:26:21 1995
  2516. +++ linux/arch/i386/mm/init.c    Mon Oct  2 14:25:10 1995
  2517. @@ -15,6 +15,7 @@
  2518.  #include <linux/ptrace.h>
  2519.  #include <linux/mman.h>
  2520.  #include <linux/mm.h>
  2521. +#include <linux/smp.h>
  2522.  
  2523.  #include <asm/system.h>
  2524.  #include <asm/segment.h>
  2525. @@ -111,10 +112,27 @@
  2526.   * and SMM (for laptops with [34]86/SL chips) may need it.  It is read
  2527.   * and write protected to detect null pointer references in the
  2528.   * kernel.
  2529. + * It may also hold the MP configuration table when we are booting SMP.
  2530.   */
  2531.  #if 0
  2532.      memset((void *) 0, 0, PAGE_SIZE);
  2533.  #endif
  2534. +#ifdef CONFIG_SMP
  2535. +    smp_scan_config(0x0,0x400);    /* Scan the bottom 1K for a signature */
  2536. +    /*
  2537. +     *    FIXME: Linux assumes you have 640K of base ram.. this continues
  2538. +     *    the error...
  2539. +     */
  2540. +    smp_scan_config(639*0x400,0x400);    /* Scan the top 1K of base RAM */
  2541. +    smp_scan_config(0xF0000,0x10000);    /* Scan the 64K of bios */
  2542. +    /*
  2543. +     *    If it is an SMP machine we should know now, unless the configuration
  2544. +     *    is in an EISA/MCA bus machine with an extended bios data area. I don't
  2545. +     *    have such a machine so someone else can fill in the check of the EBDA
  2546. +     *    here.
  2547. +     */
  2548. +/*    smp_alloc_memory(8192); */
  2549. +#endif
  2550.  #ifdef CONFIG_TEST_VERIFY_AREA
  2551.      wp_works_ok = 0;
  2552.  #endif
  2553. @@ -123,6 +141,7 @@
  2554.      pg_dir = swapper_pg_dir;
  2555.      while (address < end_mem) {
  2556.  #ifdef CONFIG_PENTIUM_MM
  2557. +#ifndef CONFIG_SMP
  2558.          if (address <= end_mem + 4*1024*1024 &&
  2559.              (x86_capability & 8)) {
  2560.  #ifdef GAS_KNOWS_CR4
  2561. @@ -144,6 +163,7 @@
  2562.              continue;
  2563.          }
  2564.  #endif
  2565. +#endif
  2566.          /* map the memory at virtual addr 0xC0000000 */
  2567.          pg_table = (pte_t *) (PAGE_MASK & pgd_val(pg_dir[768]));
  2568.          if (!pg_table) {
  2569. @@ -184,6 +204,14 @@
  2570.  
  2571.      /* mark usable pages in the mem_map[] */
  2572.      start_low_mem = PAGE_ALIGN(start_low_mem);
  2573. +
  2574. +#ifdef CONFIG_SMP
  2575. +    /*
  2576. +     * But first pinch a few for the stack/trampoline stuff
  2577. +     */
  2578. +    start_low_mem += PAGE_SIZE;                /* 32bit startup code */
  2579. +    start_low_mem = smp_alloc_memory(start_low_mem);     /* AP processor stacks */
  2580. +#endif
  2581.      start_mem = PAGE_ALIGN(start_mem);
  2582.  
  2583.      /*
  2584. diff -u --recursive --new-file v1.3.30/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
  2585. --- v1.3.30/linux/drivers/block/genhd.c    Mon Sep 25 12:26:21 1995
  2586. +++ linux/drivers/block/genhd.c    Fri Sep 29 09:27:39 1995
  2587. @@ -88,7 +88,7 @@
  2588.      this_sector = first_sector;
  2589.  
  2590.      while (1) {
  2591. -        if ((current_minor & mask) >= hd->max_p)
  2592. +        if ((current_minor & mask) == 0)
  2593.              return;
  2594.          if (!(bh = bread(dev,0,1024)))
  2595.              return;
  2596. @@ -134,7 +134,7 @@
  2597.  
  2598.              add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
  2599.              current_minor++;
  2600. -            if ((current_minor & mask) >= hd->max_p)
  2601. +            if ((current_minor & mask) == 0)
  2602.                goto done;
  2603.          }
  2604.          /*
  2605. @@ -254,8 +254,6 @@
  2606.          if (!p->nr_sects)
  2607.              continue;
  2608.          add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects);
  2609. -        if ((current_minor & 0x3f) >= 60)
  2610. -            continue;
  2611.          if (p->sys_ind == EXTENDED_PARTITION) {
  2612.              printk(" <");
  2613.              /*
  2614. @@ -280,7 +278,7 @@
  2615.          p = (struct partition *) (0x1be + data);
  2616.          for (i = 4 ; i < 16 ; i++, current_minor++) {
  2617.              p--;
  2618. -            if ((current_minor & mask) >= mask-2)
  2619. +            if ((current_minor & mask) == 0)
  2620.                  break;
  2621.              if (!(p->start_sect && p->nr_sects))
  2622.                  continue;
  2623. @@ -299,6 +297,7 @@
  2624.  static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
  2625.  {
  2626.      int i;
  2627. +    int mask = (1 << hd->minor_shift) - 1;
  2628.      struct buffer_head *bh;
  2629.      struct disklabel {
  2630.          u32 d_magic;
  2631. @@ -351,6 +350,8 @@
  2632.          return 0;
  2633.      }
  2634.      for (i = 0 ; i < label->d_npartitions; i++, partition++) {
  2635. +        if ((current_minor & mask) == 0)
  2636. +                break;
  2637.          if (partition->p_size)
  2638.              add_partition(hd, current_minor,
  2639.                  first_sector+partition->p_offset,
  2640. diff -u --recursive --new-file v1.3.30/linux/drivers/block/ide.c linux/drivers/block/ide.c
  2641. --- v1.3.30/linux/drivers/block/ide.c    Wed Sep 27 15:59:57 1995
  2642. +++ linux/drivers/block/ide.c    Fri Sep 29 09:27:28 1995
  2643. @@ -149,10 +149,9 @@
  2644.   *  Driver compile-time options are in ide.h
  2645.   *
  2646.   *  To do, in likely order of completion:
  2647. - *    - figure out why Mitsumi ATAPI cdroms are having trouble..
  2648.   *    - add ioctls to get/set interface timings on cmd640, ht6560b, triton
  2649.   *    - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
  2650. - *    - improved CMD support:  probably handing this off to someone else
  2651. + *    - improved CMD support:  handed this off to someone else
  2652.   *    - find someone to work on IDE *tape drive* support
  2653.   */
  2654.  
  2655. diff -u --recursive --new-file v1.3.30/linux/drivers/block/triton.c linux/drivers/block/triton.c
  2656. --- v1.3.30/linux/drivers/block/triton.c    Mon Sep 18 14:53:51 1995
  2657. +++ linux/drivers/block/triton.c    Fri Sep 29 09:27:28 1995
  2658. @@ -44,8 +44,14 @@
  2659.   * Testing was done with an ASUS P55TP4XE/100 system and the following drives:
  2660.   *
  2661.   *   Quantum Fireball 1080A (1Gig w/83kB buffer), DMA mode2, PIO mode4.
  2662. - *    - DMA mode2 works fine (7.4MB/sec), despite the tiny on-drive buffer.
  2663. + *    - DMA mode2 works well (7.4MB/sec), despite the tiny on-drive buffer.
  2664.   *    - This drive also does PIO mode4, at about the same speed as DMA mode2.
  2665. + *      An awesome drive for the price!
  2666. + *
  2667. + *   Fujitsu M1606TA (1Gig w/256kB buffer), DMA mode2, PIO mode4.
  2668. + *    - DMA mode2 gives horrible performance (1.6MB/sec), despite the good
  2669. + *      size of the on-drive buffer and a boasted 10ms average access time.
  2670. + *    - PIO mode4 was better, but peaked at a mere 4.5MB/sec.
  2671.   *
  2672.   *   Micropolis MC2112A (1Gig w/508kB buffer), drive pre-dates EIDE and ATA2.
  2673.   *    - DMA works fine (2.2MB/sec), probably due to the large on-drive buffer.
  2674. diff -u --recursive --new-file v1.3.30/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
  2675. --- v1.3.30/linux/drivers/char/keyboard.c    Wed Sep 27 15:59:57 1995
  2676. +++ linux/drivers/char/keyboard.c    Mon Oct  2 08:21:06 1995
  2677. @@ -1186,6 +1186,11 @@
  2678.      request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
  2679.      request_region(0x60,16,"kbd");
  2680.  #ifdef __alpha__
  2681. +    /* if there is an input byte left, eat it up: */
  2682. +    if (inb(0x64) & 0x01) {
  2683. +        inb(0x60);
  2684. +    }
  2685. +
  2686.      /* enable keyboard interrupts, PC/AT mode */
  2687.      kb_wait();
  2688.      outb(0x60,0x64);    /* write PS/2 Mode Register */
  2689. diff -u --recursive --new-file v1.3.30/linux/drivers/char/mem.c linux/drivers/char/mem.c
  2690. --- v1.3.30/linux/drivers/char/mem.c    Wed Sep 27 15:59:57 1995
  2691. +++ linux/drivers/char/mem.c    Tue Oct  3 12:14:46 1995
  2692. @@ -26,7 +26,7 @@
  2693.  extern long soundcard_init(long mem_start);
  2694.  #endif
  2695.  
  2696. -static int read_ram(struct inode * inode, struct file * file,char * buf, int count)
  2697. +static int read_ram(struct inode * inode, struct file * file, char * buf, int count)
  2698.  {
  2699.      return -EIO;
  2700.  }
  2701. @@ -36,11 +36,12 @@
  2702.      return -EIO;
  2703.  }
  2704.  
  2705. -static int read_mem(struct inode * inode, struct file * file,char * buf, int count)
  2706. +static int read_mem(struct inode * inode, struct file * file, char * buf, int count)
  2707.  {
  2708.      unsigned long p = file->f_pos;
  2709.      int read;
  2710.  
  2711. +    p += PAGE_OFFSET;
  2712.      if (count < 0)
  2713.          return -EINVAL;
  2714.      if (MAP_NR(p) >= MAP_NR(high_memory))
  2715. @@ -48,24 +49,27 @@
  2716.      if (count > high_memory - p)
  2717.          count = high_memory - p;
  2718.      read = 0;
  2719. -    while (p < PAGE_SIZE && count > 0) {
  2720. +#if defined(__i386__)        /* we don't have page 0 mapped on x86.. */
  2721. +    while (p < PAGE_OFFSET + PAGE_SIZE && count > 0) {
  2722.          put_user(0,buf);
  2723.          buf++;
  2724.          p++;
  2725.          count--;
  2726.          read++;
  2727.      }
  2728. -    memcpy_tofs(buf,(void *) p,count);
  2729. +#endif
  2730. +    memcpy_tofs(buf, (void *) p, count);
  2731.      read += count;
  2732.      file->f_pos += read;
  2733.      return read;
  2734.  }
  2735.  
  2736. -static int write_mem(struct inode * inode, struct file * file,const char * buf, int count)
  2737. +static int write_mem(struct inode * inode, struct file * file, const char * buf, int count)
  2738.  {
  2739.      unsigned long p = file->f_pos;
  2740.      int written;
  2741.  
  2742. +    p += PAGE_OFFSET;
  2743.      if (count < 0)
  2744.          return -EINVAL;
  2745.      if (MAP_NR(p) >= MAP_NR(high_memory))
  2746. @@ -73,14 +77,16 @@
  2747.      if (count > high_memory - p)
  2748.          count = high_memory - p;
  2749.      written = 0;
  2750. -    while (p < PAGE_SIZE && count > 0) {
  2751. +#if defined(__i386__)        /* we don't have page 0 mapped on x86.. */
  2752. +    while (PAGE_OFFSET + p < PAGE_SIZE && count > 0) {
  2753.          /* Hmm. Do something? */
  2754.          buf++;
  2755.          p++;
  2756.          count--;
  2757.          written++;
  2758.      }
  2759. -    memcpy_fromfs((void *) p,buf,count);
  2760. +#endif
  2761. +    memcpy_fromfs((void *) p, buf, count);
  2762.      written += count;
  2763.      file->f_pos += written;
  2764.      return count;
  2765. @@ -121,7 +127,7 @@
  2766.      return read1 + read2;
  2767.  }
  2768.  
  2769. -static int read_port(struct inode * inode,struct file * file,char * buf, int count)
  2770. +static int read_port(struct inode * inode, struct file * file,char * buf, int count)
  2771.  {
  2772.      unsigned int i = file->f_pos;
  2773.      char * tmp = buf;
  2774. @@ -135,7 +141,7 @@
  2775.      return tmp-buf;
  2776.  }
  2777.  
  2778. -static int write_port(struct inode * inode,struct file * file,const char * buf, int count)
  2779. +static int write_port(struct inode * inode, struct file * file, const char * buf, int count)
  2780.  {
  2781.      unsigned int i = file->f_pos;
  2782.      const char * tmp = buf;
  2783. @@ -149,17 +155,17 @@
  2784.      return tmp-buf;
  2785.  }
  2786.  
  2787. -static int read_null(struct inode * node,struct file * file,char * buf,int count)
  2788. +static int read_null(struct inode * node, struct file * file, char * buf, int count)
  2789.  {
  2790.      return 0;
  2791.  }
  2792.  
  2793. -static int write_null(struct inode * inode,struct file * file, const char * buf, int count)
  2794. +static int write_null(struct inode * inode, struct file * file, const char * buf, int count)
  2795.  {
  2796.      return count;
  2797.  }
  2798.  
  2799. -static int read_zero(struct inode * node,struct file * file,char * buf,int count)
  2800. +static int read_zero(struct inode * node, struct file * file, char * buf, int count)
  2801.  {
  2802.      int left;
  2803.  
  2804. @@ -179,12 +185,12 @@
  2805.      return 0;
  2806.  }
  2807.  
  2808. -static int read_full(struct inode * node,struct file * file,char * buf,int count)
  2809. +static int read_full(struct inode * node, struct file * file, char * buf,int count)
  2810.  {
  2811.      return count;
  2812.  }
  2813.  
  2814. -static int write_full(struct inode * inode,struct file * file, const char * buf, int count)
  2815. +static int write_full(struct inode * inode, struct file * file, const char * buf, int count)
  2816.  {
  2817.      return -ENOSPC;
  2818.  }
  2819. @@ -199,7 +205,7 @@
  2820.      return file->f_pos=0;
  2821.  }
  2822.  /*
  2823. - * The memory devices use the full 32 bits of the offset, and so we cannot
  2824. + * The memory devices use the full 32/64 bits of the offset, and so we cannot
  2825.   * check against negative addresses: they are ok. The return value is weird,
  2826.   * though, in that case (0).
  2827.   *
  2828. diff -u --recursive --new-file v1.3.30/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
  2829. --- v1.3.30/linux/drivers/char/msbusmouse.c    Fri Sep 15 11:13:01 1995
  2830. +++ linux/drivers/char/msbusmouse.c    Tue Oct  3 08:38:10 1995
  2831. @@ -39,6 +39,7 @@
  2832.  #endif
  2833.  
  2834.  #include <linux/kernel.h>
  2835. +#include <linux/ioport.h>
  2836.  #include <linux/sched.h>
  2837.  #include <linux/busmouse.h>
  2838.  #include <linux/signal.h>
  2839. @@ -188,6 +189,10 @@
  2840.      mouse.buttons = 0x80;
  2841.      mouse.dx = mouse.dy = 0;
  2842.      mouse.wait = NULL;
  2843. +
  2844. +    if (check_region(MS_MSE_CONTROL_PORT, 0x04))
  2845. +        return -ENODEV;
  2846. +
  2847.      if (inb_p(MS_MSE_SIGNATURE_PORT) == 0xde) {
  2848.  
  2849.          mse_byte = inb_p(MS_MSE_SIGNATURE_PORT);
  2850. @@ -210,6 +215,7 @@
  2851.  #endif
  2852.      }
  2853.      MS_MSE_INT_OFF();
  2854. +    request_region(MS_MSE_CONTROL_PORT, 0x04, "MS Busmouse");
  2855.      printk("Microsoft BusMouse detected and installed.\n");
  2856.      mouse_register(&ms_bus_mouse);
  2857.  #ifdef MODULE
  2858. @@ -224,7 +230,10 @@
  2859.  {
  2860.      if (MOD_IN_USE)
  2861.          printk("msbusmouse: in use, remove delayed\n");
  2862. -    mouse_deregister(&ms_bus_mouse);
  2863. +    else {
  2864. +        mouse_deregister(&ms_bus_mouse);
  2865. +        release_region(MS_MSE_CONTROL_PORT, 0x04);
  2866. +    }
  2867.  }
  2868.  #endif
  2869.  
  2870. diff -u --recursive --new-file v1.3.30/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
  2871. --- v1.3.30/linux/drivers/char/psaux.c    Fri Sep 15 11:13:01 1995
  2872. +++ linux/drivers/char/psaux.c    Tue Oct  3 08:27:29 1995
  2873. @@ -499,7 +499,6 @@
  2874.          printk("PS/2 auxiliary pointing device detected -- driver installed.\n");
  2875.           aux_present = 1;
  2876.          kbd_read_mask = AUX_OBUF_FULL;
  2877. -        mouse_register(&psaux_mouse);
  2878.      } else {
  2879.  #ifdef MODULE
  2880.          return -EIO;
  2881. @@ -507,6 +506,7 @@
  2882.          return kmem_start;              /* No mouse at all */
  2883.  #endif
  2884.      }
  2885. +    mouse_register(&psaux_mouse);
  2886.      queue = (struct aux_queue *) kmem_start;
  2887.      kmem_start += sizeof (struct aux_queue);
  2888.      memset(queue, 0, sizeof(*queue));
  2889. diff -u --recursive --new-file v1.3.30/linux/drivers/char/random.c linux/drivers/char/random.c
  2890. --- v1.3.30/linux/drivers/char/random.c    Wed Sep 27 15:59:57 1995
  2891. +++ linux/drivers/char/random.c    Tue Oct  3 08:10:41 1995
  2892. @@ -426,16 +426,19 @@
  2893.  
  2894.  #if defined (__i386__)
  2895.      /*
  2896. -     * On a 386, read the high resolution timer.  We assume that
  2897. -     * this gives us 2 bits of randomness.  XXX This needs
  2898. +     * On a Pentium, read the cycle counter. We assume that
  2899. +     * this gives us 8 bits of randomness.  XXX This needs
  2900.       * investigation.
  2901. -     */ 
  2902. -    outb_p(0x00, 0x43);    /* latch the count ASAP */
  2903. -    add_entropy_byte(r, inb_p(0x40), 1);
  2904. -    add_entropy_byte(r, inb(0x40), 1);
  2905. -    r->entropy_count += 2;
  2906. -    if (r->entropy_count > r->bit_length)
  2907. -        r->entropy_count = r->bit_length;
  2908. +     */
  2909. +    if (x86_capability & 16) {
  2910. +        unsigned long low, high;
  2911. +        __asm__(".byte 0x0f,0x31"
  2912. +            :"=a" (low), "=d" (high));
  2913. +        add_entropy_byte(r, low, 1);
  2914. +        r->entropy_count += 8;
  2915. +        if (r->entropy_count > r->bit_length)
  2916. +            r->entropy_count = r->bit_length;
  2917. +    }
  2918.  #endif
  2919.  }
  2920.  
  2921. diff -u --recursive --new-file v1.3.30/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
  2922. --- v1.3.30/linux/drivers/net/3c501.c    Sat Sep  9 15:26:52 1995
  2923. +++ linux/drivers/net/3c501.c    Wed Oct  4 08:15:11 1995
  2924. @@ -654,6 +654,7 @@
  2925.  }
  2926.  
  2927.  /* Set or clear the multicast filter for this adaptor.
  2928. +   num_addrs == -2    All multicast hosts
  2929.     num_addrs == -1    Promiscuous mode, receive all packets
  2930.     num_addrs == 0    Normal mode, clear multicast list
  2931.     num_addrs > 0    Multicast mode, receive normal and MC packets, and do
  2932. @@ -664,8 +665,8 @@
  2933.  {
  2934.      int ioaddr = dev->base_addr;
  2935.  
  2936. -    if (num_addrs > 0) {
  2937. -    outb(RX_MULT, RX_CMD);
  2938. +    if (num_addrs > 0 || num_addrs==-2) {
  2939. +    outb(RX_MULT, RX_CMD);    /* Multicast or all multicast is the same */
  2940.      inb(RX_STATUS);        /* Clear status. */
  2941.      } else if (num_addrs < 0) {
  2942.      outb(RX_PROM, RX_CMD);
  2943. diff -u --recursive --new-file v1.3.30/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
  2944. --- v1.3.30/linux/drivers/net/3c503.c    Sun Sep  3 12:26:53 1995
  2945. +++ linux/drivers/net/3c503.c    Sun Oct  1 19:18:58 1995
  2946. @@ -71,8 +71,10 @@
  2947.  static void el2_init_card(struct device *dev);
  2948.  static void el2_block_output(struct device *dev, int count,
  2949.                   const unsigned char *buf, const start_page);
  2950. -static int el2_block_input(struct device *dev, int count, char *buf,
  2951. +static void el2_block_input(struct device *dev, int count, struct sk_buff *skb,
  2952.                 int ring_offset);
  2953. +static void el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  2954. +             int ring_page);
  2955.  
  2956.  
  2957.  /* This routine probes for a memory-mapped 3c503 board by looking for
  2958. @@ -148,6 +150,7 @@
  2959.  {
  2960.      int i, iobase_reg, membase_reg, saved_406;
  2961.      static unsigned version_printed = 0;
  2962. +    unsigned long vendor_id;
  2963.  
  2964.      /* Reset and/or avoid any lurking NE2000 */
  2965.      if (inb(ioaddr + 0x408) == 0xff) {
  2966. @@ -167,11 +170,11 @@
  2967.      saved_406 = inb_p(ioaddr + 0x406);
  2968.      outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
  2969.      outb_p(ECNTRL_THIN, ioaddr + 0x406);
  2970. -    /* Map the station addr PROM into the lower I/O ports. */
  2971. +    /* Map the station addr PROM into the lower I/O ports. We now check
  2972. +       for both the old and new 3Com prefix */
  2973.      outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
  2974. -    if (   inb(ioaddr + 0) != 0x02
  2975. -    || inb(ioaddr + 1) != 0x60
  2976. -    || inb(ioaddr + 2) != 0x8c) {
  2977. +    vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
  2978. +    if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
  2979.      /* Restore the register we frobbed. */
  2980.      outb(saved_406, ioaddr + 0x406);
  2981.      return ENODEV;
  2982. @@ -250,6 +253,7 @@
  2983.      ei_status.rx_start_page = EL2SM_START_PG + TX_PAGES;
  2984.      ei_status.stop_page = EL2SM_STOP_PG;
  2985.      ei_status.reset_8390 = &el2_reset_8390;
  2986. +    ei_status.get_8390_hdr = &el2_get_8390_hdr;
  2987.      ei_status.block_input = &el2_block_input;
  2988.      ei_status.block_output = &el2_block_output;
  2989.  
  2990. @@ -268,7 +272,7 @@
  2991.      dev->stop = &el2_close;
  2992.  
  2993.      if (dev->mem_start)
  2994. -    printk("\n%s: %s with shared memory at %#6lx-%#6lx,\n",
  2995. +    printk("\n%s: %s with shared memory at %#6lx-%#6lx.\n",
  2996.             dev->name, ei_status.name, dev->mem_start, dev->mem_end-1);
  2997.      else
  2998.      printk("\n%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).\n",
  2999. @@ -388,12 +392,9 @@
  3000.      outb(EGACFR_NORM, E33G_GACFR);    /* Enable RAM and interrupts. */
  3001.  
  3002.      if (dev->mem_start) {    /* Shared memory transfer */
  3003. -    void *dest_addr = (void *)(dev->mem_start +
  3004. -        ((start_page - ei_status.tx_start_page) << 8));
  3005. -    memcpy(dest_addr, buf, count);
  3006. -    if (ei_debug > 2  &&  memcmp(dest_addr, buf, count))
  3007. -        printk("%s: 3c503 send_packet() bad memory copy @ %#5x.\n",
  3008. -           dev->name, (int) dest_addr);
  3009. +    unsigned long dest_addr = dev->mem_start +
  3010. +        ((start_page - ei_status.tx_start_page) << 8);
  3011. +    memcpy_toio(dest_addr, buf, count);
  3012.      return;
  3013.      }
  3014.      /* No shared memory, put the packet out the slow way. */
  3015. @@ -420,9 +421,34 @@
  3016.      return;
  3017.  }
  3018.  
  3019. +/* Read the 4 byte, page aligned 8390 specific header. */
  3020. +static void
  3021. +el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  3022. +{
  3023. +    unsigned int i;
  3024. +    unsigned long hdr_start = dev->mem_start + ((ring_page - EL2SM_START_PG)<<8);
  3025. +
  3026. +    if (dev->mem_start) {       /* Use the shared memory. */
  3027. +    memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
  3028. +    return;
  3029. +    }
  3030. +
  3031. +    /* No shared memory, use programmed I/O. Ugh. */
  3032. +    outb(0, E33G_DMAAL);
  3033. +    outb_p(ring_page & 0xff, E33G_DMAAH);
  3034. +    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
  3035. +       | ECNTRL_START, E33G_CNTRL);
  3036. +
  3037. +    /* Header is less than 8 bytes, so we can ignore the FIFO. */
  3038. +    for(i = 0; i < sizeof(struct e8390_pkt_hdr); i++)
  3039. +    ((char *)(hdr))[i] = inb_p(E33G_FIFOH);
  3040. +
  3041. +    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
  3042. +}
  3043. +
  3044.  /* Returns the new ring pointer. */
  3045. -static int
  3046. -el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
  3047. +static void
  3048. +el2_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  3049.  {
  3050.      int boguscount = 0;
  3051.      int end_of_ring = dev->rmem_end;
  3052. @@ -434,13 +460,14 @@
  3053.      if (dev->mem_start + ring_offset + count > end_of_ring) {
  3054.          /* We must wrap the input move. */
  3055.          int semi_count = end_of_ring - (dev->mem_start + ring_offset);
  3056. -        memcpy(buf, (char *)dev->mem_start + ring_offset, semi_count);
  3057. +        memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
  3058.          count -= semi_count;
  3059. -        memcpy(buf + semi_count, (char *)dev->rmem_start, count);
  3060. -        return dev->rmem_start + count;
  3061. +        memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
  3062. +    } else {
  3063. +        /* Packet is in one chunk -- we can copy + cksum. */
  3064. +        eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
  3065.      }
  3066. -    memcpy(buf, (char *)dev->mem_start + ring_offset, count);
  3067. -    return ring_offset + count;
  3068. +    return;
  3069.      }
  3070.      /* No shared memory, use programmed I/O. */
  3071.      outb(ring_offset & 0xff, E33G_DMAAL);
  3072. @@ -459,10 +486,9 @@
  3073.              boguscount = 0;
  3074.              break;
  3075.          }
  3076. -    buf[i] = inb_p(E33G_FIFOH);
  3077. +    (skb->data)[i] = inb_p(E33G_FIFOH);
  3078.      }
  3079.      outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
  3080. -    return 0;
  3081.  }
  3082.  #ifdef MODULE
  3083.  char kernel_version[] = UTS_RELEASE;
  3084. diff -u --recursive --new-file v1.3.30/linux/drivers/net/3c503.h linux/drivers/net/3c503.h
  3085. --- v1.3.30/linux/drivers/net/3c503.h    Wed Dec  1 14:44:15 1993
  3086. +++ linux/drivers/net/3c503.h    Sun Oct  1 19:18:58 1995
  3087. @@ -6,6 +6,12 @@
  3088.  #define EL2H (dev->base_addr + 0x400)
  3089.  #define EL2L (dev->base_addr)
  3090.  
  3091. +/* Vendor unique hardware addr. prefix. 3Com has 2 because they ran
  3092. +   out of available addresses on the first one... */
  3093. +
  3094. +#define OLD_3COM_ID    0x02608c
  3095. +#define NEW_3COM_ID    0x0020af
  3096. +
  3097.  /* Shared memory management parameters */
  3098.  
  3099.  #define EL2SM_START_PG    (0x20)    /* First page of TX buffer */
  3100. diff -u --recursive --new-file v1.3.30/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
  3101. --- v1.3.30/linux/drivers/net/3c509.c    Sat Sep  9 15:26:52 1995
  3102. +++ linux/drivers/net/3c509.c    Wed Oct  4 08:15:11 1995
  3103. @@ -262,7 +262,7 @@
  3104.      dev->stop = &el3_close;
  3105.      dev->get_stats = &el3_get_stats;
  3106.  #ifdef HAVE_MULTICAST
  3107. -        dev->set_multicast_list = &set_multicast_list;
  3108. +    dev->set_multicast_list = &set_multicast_list;
  3109.  #endif
  3110.  
  3111.      /* Fill in the generic fields of the device structure. */
  3112. @@ -652,7 +652,7 @@
  3113.              printk("%s: Setting Rx mode to %d addresses.\n", dev->name, num_addrs);
  3114.          }
  3115.      }
  3116. -    if (num_addrs > 0) {
  3117. +    if (num_addrs > 0 || num_addrs == -2) {
  3118.          outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
  3119.      } else if (num_addrs < 0) {
  3120.          outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
  3121. diff -u --recursive --new-file v1.3.30/linux/drivers/net/8390.c linux/drivers/net/8390.c
  3122. --- v1.3.30/linux/drivers/net/8390.c    Sat Sep  9 15:26:52 1995
  3123. +++ linux/drivers/net/8390.c    Wed Oct  4 08:15:11 1995
  3124. @@ -19,6 +19,8 @@
  3125.    Changelog:
  3126.  
  3127.    Paul Gortmaker    : remove set_bit lock, other cleanups.
  3128. +  Paul Gortmaker    : add ei_get_8390_hdr() so we can pass skb's to 
  3129. +              ei_block_input() for eth_io_copy_and_sum().
  3130.  
  3131.    */
  3132.  
  3133. @@ -70,15 +72,18 @@
  3134.                        int start_page)
  3135.          Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
  3136.          "page" value uses the 8390's 256-byte pages.
  3137. -    int block_input(struct device *dev, int count, char *buf, int ring_offset)
  3138. -        Read COUNT bytes from the packet buffer into BUF.  Start reading from
  3139. -        RING_OFFSET, the address as the 8390 sees it.  The first read will
  3140. -        always be the 4 byte, page aligned 8390 header.  *If* there is a
  3141. +    void get_8390_hdr(struct device *dev, struct e8390_hdr *hdr, int ring_page)
  3142. +        Read the 4 byte, page aligned 8390 header. *If* there is a
  3143.          subsequent read, it will be of the rest of the packet.
  3144. +    void block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  3145. +        Read COUNT bytes from the packet buffer into the skb data area. Start 
  3146. +        reading from RING_OFFSET, the address as the 8390 sees it.  This will always
  3147. +        follow the read of the 8390 header. 
  3148.  */
  3149.  #define ei_reset_8390 (ei_local->reset_8390)
  3150.  #define ei_block_output (ei_local->block_output)
  3151.  #define ei_block_input (ei_local->block_input)
  3152. +#define ei_get_8390_hdr (ei_local->get_8390_hdr)
  3153.  
  3154.  /* use 0 for production, 1 for verification, >2 for debug */
  3155.  #ifdef EI_DEBUG
  3156. @@ -152,17 +157,16 @@
  3157.              printk("%s: xmit on stopped card\n", dev->name);
  3158.              return 1;
  3159.          }
  3160. -        printk(KERN_DEBUG "%s: transmit timed out, TX status %#2x, ISR %#2x.\n",
  3161. -               dev->name, txsr, isr);
  3162. -        /* Does the 8390 thinks it has posted an interrupt? */
  3163. -        if (isr)
  3164. -            printk(KERN_DEBUG "%s: Possible IRQ conflict on IRQ%d?\n", dev->name, dev->irq);
  3165. -        else {
  3166. -            /* The 8390 probably hasn't gotten on the cable yet. */
  3167. -            printk(KERN_DEBUG "%s: Possible network cable problem?\n", dev->name);
  3168. -            if(ei_local->stat.tx_packets==0)
  3169. -                ei_local->interface_num ^= 1;     /* Try a different xcvr.  */
  3170. +
  3171. +        printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
  3172. +           dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
  3173. +           (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
  3174. +
  3175. +        if (!isr && !ei_local->stat.tx_packets) {
  3176. +           /* The 8390 probably hasn't gotten on the cable yet. */
  3177. +           ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
  3178.          }
  3179. +
  3180.          /* Try to restart the card.  Perhaps the user has fixed something. */
  3181.          ei_reset_8390(dev);
  3182.          NS8390_init(dev, 1);
  3183. @@ -312,7 +316,7 @@
  3184.  
  3185.          /* Ignore any RDC interrupts that make it back to here. */
  3186.          if (interrupts & ENISR_RDC) {
  3187. -                outb_p(ENISR_RDC, e8390_base + EN0_ISR);
  3188. +            outb_p(ENISR_RDC, e8390_base + EN0_ISR);
  3189.          }
  3190.  
  3191.          outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
  3192. @@ -431,10 +435,9 @@
  3193.              break;                /* Done for now */
  3194.          
  3195.          current_offset = this_frame << 8;
  3196. -        ei_block_input(dev, sizeof(rx_frame), (char *)&rx_frame,
  3197. -                       current_offset);
  3198. +        ei_get_8390_hdr(dev, &rx_frame, this_frame);
  3199.          
  3200. -        pkt_len = rx_frame.count - sizeof(rx_frame);
  3201. +        pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
  3202.          
  3203.          next_frame = this_frame + 1 + ((pkt_len+4)>>8);
  3204.          
  3205. @@ -470,9 +473,8 @@
  3206.              } else {
  3207.                  skb_reserve(skb,2);    /* IP headers on 16 byte boundaries */
  3208.                  skb->dev = dev;
  3209. -                
  3210. -                ei_block_input(dev, pkt_len, skb_put(skb,pkt_len),
  3211. -                               current_offset + sizeof(rx_frame));
  3212. +                skb_put(skb, pkt_len);    /* Make room */
  3213. +                ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
  3214.                  skb->protocol=eth_type_trans(skb,dev);
  3215.                  netif_rx(skb);
  3216.                  ei_local->stat.rx_packets++;
  3217. @@ -533,7 +535,7 @@
  3218.         easy way of timing something in that range, so we use 'jiffies' as
  3219.         a sanity check. */
  3220.      while ((inb_p(e8390_base+EN0_ISR) & ENISR_RESET) == 0)
  3221. -        if (jiffies - reset_start_time > 1) {
  3222. +        if (jiffies - reset_start_time > 2*HZ/100) {
  3223.              printk("%s: reset did not complete at ei_rx_overrun.\n",
  3224.                     dev->name);
  3225.              NS8390_init(dev, 1);
  3226. @@ -576,7 +578,7 @@
  3227.  {
  3228.      short ioaddr = dev->base_addr;
  3229.      
  3230. -    if (num_addrs > 0) {
  3231. +    if (num_addrs > 0 || num_addrs == -2) {
  3232.          /* The multicast-accept list is initialized to accept-all, and we
  3233.             rely on higher-level filtering for now. */
  3234.          outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
  3235. diff -u --recursive --new-file v1.3.30/linux/drivers/net/8390.h linux/drivers/net/8390.h
  3236. --- v1.3.30/linux/drivers/net/8390.h    Wed Aug  2 13:21:02 1995
  3237. +++ linux/drivers/net/8390.h    Sun Oct  1 19:18:58 1995
  3238. @@ -9,6 +9,7 @@
  3239.  
  3240.  #include <linux/if_ether.h>
  3241.  #include <linux/ioport.h>
  3242. +#include <linux/skbuff.h>
  3243.  
  3244.  #define TX_2X_PAGES 12
  3245.  #define TX_1X_PAGES 6
  3246. @@ -16,6 +17,13 @@
  3247.  
  3248.  #define ETHER_ADDR_LEN 6
  3249.  
  3250. +/* The 8390 specific per-packet-header format. */
  3251. +struct e8390_pkt_hdr {
  3252. +  unsigned char status; /* status */
  3253. +  unsigned char next;   /* pointer to next packet. */
  3254. +  unsigned short count; /* header + packet length in bytes */
  3255. +};
  3256. +
  3257.  /* From 8390.c */
  3258.  extern int ei_debug;
  3259.  extern struct sigaction ei_sigaction;
  3260. @@ -39,8 +47,9 @@
  3261.  struct ei_device {
  3262.    const char *name;
  3263.    void (*reset_8390)(struct device *);
  3264. +  void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
  3265.    void (*block_output)(struct device *, int, const unsigned char *, int);
  3266. -  int  (*block_input)(struct device *, int, char *, int);
  3267. +  void (*block_input)(struct device *, int, struct sk_buff *, int);
  3268.    unsigned open:1;
  3269.    unsigned word16:1;  /* We have the 16-bit (vs 8-bit) version of the card. */
  3270.    unsigned txing:1;        /* Transmit Active */
  3271. @@ -63,8 +72,8 @@
  3272.  /* The maximum number of 8390 interrupt service routines called per IRQ. */
  3273.  #define MAX_SERVICE 12
  3274.  
  3275. -/* The maximum number of jiffies waited before assuming a Tx failed. */
  3276. -#define TX_TIMEOUT 20 
  3277. +/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */
  3278. +#define TX_TIMEOUT (20*HZ/100)
  3279.  
  3280.  #define ei_status (*(struct ei_device *)(dev->priv))
  3281.  
  3282. @@ -155,10 +164,4 @@
  3283.  #define ENTSR_CDH 0x40    /* The collision detect "heartbeat" signal was lost. */
  3284.  #define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
  3285.  
  3286. -/* The per-packet-header format. */
  3287. -struct e8390_pkt_hdr {
  3288. -  unsigned char status; /* status */
  3289. -  unsigned char next;   /* pointer to next packet. */
  3290. -  unsigned short count; /* header + packet length in bytes */
  3291. -};
  3292.  #endif /* _8390_h */
  3293. diff -u --recursive --new-file v1.3.30/linux/drivers/net/CONFIG linux/drivers/net/CONFIG
  3294. --- v1.3.30/linux/drivers/net/CONFIG    Wed Aug  9 14:55:39 1995
  3295. +++ linux/drivers/net/CONFIG    Sun Oct  1 19:18:58 1995
  3296. @@ -9,15 +9,14 @@
  3297.  #
  3298.  #  CONFIG_WD80x3    The Western Digital (SMC) WD80x3 driver
  3299.  #    WD_SHMEM=xxx    Forces the address of the shared memory
  3300. -#    WD_no_mapout    Don't map out the shared memory (faster, but
  3301. -#            your machine may not warm-boot).
  3302.  #  CONFIG_NE2000    The NE-[12]000 clone driver.
  3303.  #    PACKETBUF_MEMSIZE  Allows an extra-large packet buffer to be
  3304.  #            used.  Usually pointless under Linux.
  3305.  #    show_all_SAPROM  Show the entire address PROM, not just the
  3306.  #            ethernet address, during boot.
  3307.  #    CONFIG_NE_RW_BUGFIX  Patch an obscure bug with a version of the 8390.
  3308. -#    CONFIG_NE_SANITY ??
  3309. +#    CONFIG_NE_SANITY Double check the internal card xfer address
  3310. +#            against the driver's value. Useful for debugging.
  3311.  #  CONFIG_HPLAN        The HP-LAN driver (for 8390-based boards only).
  3312.  #    rw_bugfix    Fix the same obscure bug.
  3313.  #  CONFIG_EL2        The 3c503 EtherLink II driver
  3314. diff -u --recursive --new-file v1.3.30/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
  3315. --- v1.3.30/linux/drivers/net/ac3200.c    Tue Aug 15 20:39:02 1995
  3316. +++ linux/drivers/net/ac3200.c    Sun Oct  1 19:18:58 1995
  3317. @@ -29,6 +29,7 @@
  3318.  #include <asm/io.h>
  3319.  
  3320.  #include <linux/netdevice.h>
  3321. +#include <linux/etherdevice.h>
  3322.  #include "8390.h"
  3323.  
  3324.  /* Offsets from the base address. */
  3325. @@ -72,10 +73,13 @@
  3326.  
  3327.  static int ac_open(struct device *dev);
  3328.  static void ac_reset_8390(struct device *dev);
  3329. -static int ac_block_input(struct device *dev, int count,
  3330. -                          char *buf, int ring_offset);
  3331. +static void ac_block_input(struct device *dev, int count,
  3332. +                    struct sk_buff *skb, int ring_offset);
  3333.  static void ac_block_output(struct device *dev, const int count,
  3334.                              const unsigned char *buf, const int start_page);
  3335. +static void ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  3336. +                    int ring_page);
  3337. +
  3338.  static int ac_close_card(struct device *dev);
  3339.  
  3340.  
  3341. @@ -195,6 +199,7 @@
  3342.      ei_status.reset_8390 = &ac_reset_8390;
  3343.      ei_status.block_input = &ac_block_input;
  3344.      ei_status.block_output = &ac_block_output;
  3345. +    ei_status.get_8390_hdr = &ac_get_8390_hdr;
  3346.  
  3347.      dev->open = &ac_open;
  3348.      dev->stop = &ac_close_card;
  3349. @@ -237,33 +242,43 @@
  3350.      return;
  3351.  }
  3352.  
  3353. +/* Grab the 8390 specific header. Similar to the block_input routine, but
  3354. +   we don't need to be concerned with ring wrap as the header will be at
  3355. +   the start of a page, so we optimize accordingly. */
  3356. +
  3357. +static void
  3358. +ac_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  3359. +{
  3360. +    unsigned long hdr_start = dev->mem_start + ((ring_page - AC_START_PG)<<8);
  3361. +    memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
  3362. +}
  3363. +
  3364.  /*  Block input and output are easy on shared memory ethercards, the only
  3365.      complication is when the ring buffer wraps. */
  3366.  
  3367. -static int ac_block_input(struct device *dev, int count, char *buf,
  3368. +static void ac_block_input(struct device *dev, int count, struct sk_buff *skb,
  3369.                            int ring_offset)
  3370.  {
  3371. -    long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
  3372. +    unsigned long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
  3373.  
  3374.      if (xfer_start + count > dev->rmem_end) {
  3375.          /* We must wrap the input move. */
  3376.          int semi_count = dev->rmem_end - xfer_start;
  3377. -        memcpy(buf, (char*)xfer_start, semi_count);
  3378. +        memcpy_fromio(skb->data, xfer_start, semi_count);
  3379.          count -= semi_count;
  3380. -        memcpy(buf + semi_count, (char *)dev->rmem_start, count);
  3381. -        return dev->rmem_start + count;
  3382. +        memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
  3383. +    } else {
  3384. +        /* Packet is in one chunk -- we can copy + cksum. */
  3385. +        eth_io_copy_and_sum(skb, xfer_start, count, 0);
  3386.      }
  3387. -    memcpy(buf, (char*)xfer_start, count);
  3388. -
  3389. -    return ring_offset + count;
  3390.  }
  3391.  
  3392.  static void ac_block_output(struct device *dev, int count,
  3393.                              const unsigned char *buf, int start_page)
  3394.  {
  3395. -    long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
  3396. +    unsigned long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
  3397.  
  3398. -    memcpy((unsigned char *)shmem, buf, count);
  3399. +    memcpy_toio(shmem, buf, count);
  3400.  }
  3401.  
  3402.  static int ac_close_card(struct device *dev)
  3403. diff -u --recursive --new-file v1.3.30/linux/drivers/net/e2100.c linux/drivers/net/e2100.c
  3404. --- v1.3.30/linux/drivers/net/e2100.c    Tue Aug 15 20:39:03 1995
  3405. +++ linux/drivers/net/e2100.c    Sun Oct  1 19:18:58 1995
  3406. @@ -19,7 +19,7 @@
  3407.      station address region, and the low three bits of next outb() *address*
  3408.      is used    as the write value for that register.  Either someone wasn't
  3409.      too used to dem bit en bites, or they were trying to obfuscate the
  3410. -    programming    interface.
  3411. +    programming interface.
  3412.  
  3413.      There is an additional complication when setting the window on the packet
  3414.      buffer.  You must first do a read into the packet buffer region with the
  3415. @@ -48,6 +48,7 @@
  3416.  #include <linux/ioport.h>
  3417.  
  3418.  #include <linux/netdevice.h>
  3419. +#include <linux/etherdevice.h>
  3420.  #include "8390.h"
  3421.  
  3422.  static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
  3423. @@ -99,10 +100,13 @@
  3424.  
  3425.  static int e21_open(struct device *dev);
  3426.  static void e21_reset_8390(struct device *dev);
  3427. -static int e21_block_input(struct device *dev, int count,
  3428. -                           char *buf, int ring_offset);
  3429. +static void e21_block_input(struct device *dev, int count,
  3430. +                           struct sk_buff *skb, int ring_offset);
  3431.  static void e21_block_output(struct device *dev, int count,
  3432.                               const unsigned char *buf, const start_page);
  3433. +static void e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  3434. +                            int ring_page);
  3435. +
  3436.  static int e21_close(struct device *dev);
  3437.  
  3438.  
  3439. @@ -189,7 +193,7 @@
  3440.      ei_status.tx_start_page = E21_TX_START_PG;
  3441.      ei_status.rx_start_page = E21_RX_START_PG;
  3442.      ei_status.stop_page = E21_RX_STOP_PG;
  3443. -    ei_status.saved_irq = dev->irq;
  3444. +    ei_status.saved_irq = dev->irq;
  3445.  
  3446.      /* Check the media port used.  The port can be passed in on the
  3447.         low mem_end bits. */
  3448. @@ -227,6 +231,7 @@
  3449.      ei_status.reset_8390 = &e21_reset_8390;
  3450.      ei_status.block_input = &e21_block_input;
  3451.      ei_status.block_output = &e21_block_output;
  3452. +    ei_status.get_8390_hdr = &e21_get_8390_hdr;
  3453.      dev->open = &e21_open;
  3454.      dev->stop = &e21_close;
  3455.      NS8390_init(dev, 0);
  3456. @@ -277,28 +282,40 @@
  3457.      return;
  3458.  }
  3459.  
  3460. +/* Grab the 8390 specific header. We put the 2k window so the header page
  3461. +   appears at the start of the shared memory. */
  3462. +
  3463. +static void
  3464. +e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  3465. +{
  3466. +
  3467. +    short ioaddr = dev->base_addr;
  3468. +    char *shared_mem = (char *)dev->mem_start;
  3469. +
  3470. +    mem_on(ioaddr, shared_mem, ring_page);
  3471. +
  3472. +    memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
  3473. +
  3474. +    /* Turn off memory access: we would need to reprogram the window anyway. */
  3475. +    mem_off(ioaddr);
  3476. +
  3477. +}
  3478. +
  3479.  /*  Block input and output are easy on shared memory ethercards.
  3480.      The E21xx makes block_input() especially easy by wrapping the top
  3481.      ring buffer to the bottom automatically. */
  3482. -static int
  3483. -e21_block_input(struct device *dev, int count, char *buf, int ring_offset)
  3484. +static void
  3485. +e21_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  3486.  {
  3487.      short ioaddr = dev->base_addr;
  3488.      char *shared_mem = (char *)dev->mem_start;
  3489. -    int start_page = (ring_offset>>8);
  3490.  
  3491. -    mem_on(ioaddr, shared_mem, start_page);
  3492. +    mem_on(ioaddr, shared_mem, (ring_offset>>8));
  3493.  
  3494. -    /* We'll always get a 4 byte header read first. */
  3495. -    if (count == 4)
  3496. -        ((int*)buf)[0] = ((int*)shared_mem)[0];
  3497. -    else
  3498. -        memcpy(buf, shared_mem + (ring_offset & 0xff), count);
  3499. +    /* Packet is always in one chunk -- we can copy + cksum. */
  3500. +    eth_io_copy_and_sum(skb, dev->mem_start + (ring_offset & 0xff), count, 0);
  3501.  
  3502. -    /* Turn off memory access: we would need to reprogram the window anyway. */
  3503.      mem_off(ioaddr);
  3504. -
  3505. -    return 0;
  3506.  }
  3507.  
  3508.  static void
  3509. @@ -310,10 +327,10 @@
  3510.  
  3511.      /* Set the shared memory window start by doing a read, with the low address
  3512.         bits specifying the starting page. */
  3513. -    *(shared_mem + start_page);
  3514. +    readb(shared_mem + start_page);
  3515.      mem_on(ioaddr, shared_mem, start_page);
  3516.  
  3517. -    memcpy((char*)shared_mem, buf, count);
  3518. +    memcpy_toio(shared_mem, buf, count);
  3519.      mem_off(ioaddr);
  3520.  }
  3521.  
  3522. diff -u --recursive --new-file v1.3.30/linux/drivers/net/eql.c linux/drivers/net/eql.c
  3523. --- v1.3.30/linux/drivers/net/eql.c    Sat Sep  9 15:26:52 1995
  3524. +++ linux/drivers/net/eql.c    Mon Oct  2 14:25:10 1995
  3525. @@ -25,7 +25,7 @@
  3526.   * Inspirations:
  3527.   *   The Harried and Overworked Alan Cox
  3528.   * Conspiracies:
  3529. - *   The Alan Cox and Arisian plot to get someone else to do the code, which
  3530. + *   The Alan Cox and Mike McLagan plot to get someone else to do the code, which
  3531.   *   turned out to be me.
  3532.   */
  3533.  
  3534. diff -u --recursive --new-file v1.3.30/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
  3535. --- v1.3.30/linux/drivers/net/hp-plus.c    Tue Aug 15 20:39:03 1995
  3536. +++ linux/drivers/net/hp-plus.c    Sun Oct  1 19:18:58 1995
  3537. @@ -101,14 +101,18 @@
  3538.  static void hpp_reset_8390(struct device *dev);
  3539.  static int hpp_open(struct device *dev);
  3540.  static int hpp_close(struct device *dev);
  3541. -static int hpp_mem_block_input(struct device *dev, int count,
  3542. -                          char *buf, int ring_offset);
  3543. +static void hpp_mem_block_input(struct device *dev, int count,
  3544. +                          struct sk_buff *skb, int ring_offset);
  3545.  static void hpp_mem_block_output(struct device *dev, int count,
  3546.                              const unsigned char *buf, const start_page);
  3547. -static int hpp_io_block_input(struct device *dev, int count,
  3548. -                          char *buf, int ring_offset);
  3549. +static void hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  3550. +                          int ring_page);
  3551. +static void hpp_io_block_input(struct device *dev, int count,
  3552. +                          struct sk_buff *skb, int ring_offset);
  3553.  static void hpp_io_block_output(struct device *dev, int count,
  3554.                              const unsigned char *buf, const start_page);
  3555. +static void hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  3556. +                          int ring_page);
  3557.  
  3558.  
  3559.  /*    Probe a list of addresses for an HP LAN+ adaptor.
  3560. @@ -221,11 +225,13 @@
  3561.      ei_status.reset_8390 = &hpp_reset_8390;
  3562.      ei_status.block_input = &hpp_io_block_input;
  3563.      ei_status.block_output = &hpp_io_block_output;
  3564. +    ei_status.get_8390_hdr = &hpp_io_get_8390_hdr;
  3565.  
  3566.      /* Check if the memory_enable flag is set in the option register. */
  3567.      if (mem_start) {
  3568.          ei_status.block_input = &hpp_mem_block_input;
  3569.          ei_status.block_output = &hpp_mem_block_output;
  3570. +        ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr;
  3571.          dev->mem_start = mem_start;
  3572.          dev->rmem_start = dev->mem_start + TX_2X_PAGES*256;
  3573.          dev->mem_end = dev->rmem_end
  3574. @@ -307,23 +313,49 @@
  3575.      return;
  3576.  }
  3577.  
  3578. -/* Block input and output, similar to the Crynwr packet driver.
  3579. +/* The programmed-I/O version of reading the 4 byte 8390 specific header.
  3580.     Note that transfer with the EtherTwist+ must be on word boundaries. */
  3581.  
  3582. -static int
  3583. -hpp_io_block_input(struct device *dev, int count, char *buf, int ring_offset)
  3584. +static void
  3585. +hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  3586. +{
  3587. +    int ioaddr = dev->base_addr - NIC_OFFSET;
  3588. +
  3589. +    outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
  3590. +    insw(ioaddr + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
  3591. +}
  3592. +
  3593. +/* Block input and output, similar to the Crynwr packet driver. */
  3594. +
  3595. +static void
  3596. +hpp_io_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  3597.  {
  3598.      int ioaddr = dev->base_addr - NIC_OFFSET;
  3599. +    char *buf = skb->data;
  3600.  
  3601.      outw(ring_offset, ioaddr + HPP_IN_ADDR);
  3602.      insw(ioaddr + HP_DATAPORT, buf, count>>1);
  3603.      if (count & 0x01)
  3604.          buf[count-1] = inw(ioaddr + HP_DATAPORT);
  3605. -    return ring_offset + count;
  3606.  }
  3607.  
  3608. -static int
  3609. -hpp_mem_block_input(struct device *dev, int count, char *buf, int ring_offset)
  3610. +/* The corresponding shared memory versions of the above 2 functions. */
  3611. +
  3612. +static void
  3613. +hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  3614. +{
  3615. +    int ioaddr = dev->base_addr - NIC_OFFSET;
  3616. +    int option_reg = inw(ioaddr + HPP_OPTION);
  3617. +
  3618. +    outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
  3619. +    outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
  3620. +    memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr));
  3621. +    outw(option_reg, ioaddr + HPP_OPTION);
  3622. +    hdr->count = (hdr->count + 3) & ~3;    /* Round up allocation. */
  3623. +}
  3624. +
  3625. +static void
  3626. +hpp_mem_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  3627.  {
  3628.      int ioaddr = dev->base_addr - NIC_OFFSET;
  3629.      int option_reg = inw(ioaddr + HPP_OPTION);
  3630. @@ -331,11 +363,13 @@
  3631.      outw(ring_offset, ioaddr + HPP_IN_ADDR);
  3632.  
  3633.      outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
  3634. -    /* Caution: this relies on 8390.c rounding up allocations! */
  3635. -    memcpy(buf, (char*)dev->mem_start,  (count + 3) & ~3);
  3636. -    outw(option_reg, ioaddr + HPP_OPTION);
  3637.  
  3638. -    return ring_offset + count;
  3639. +    /* Caution: this relies on get_8390_hdr() rounding up count!
  3640. +       Also note that we *can't* use eth_io_copy_and_sum() because
  3641. +       it will not always copy "count" bytes (e.g. padded IP).  */
  3642. +
  3643. +    memcpy_fromio(skb->data, dev->mem_start, count);
  3644. +    outw(option_reg, ioaddr + HPP_OPTION);
  3645.  }
  3646.  
  3647.  /* A special note: we *must* always transfer >=16 bit words.
  3648. @@ -359,7 +393,7 @@
  3649.  
  3650.      outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
  3651.      outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
  3652. -    memcpy((char *)dev->mem_start, buf, (count + 3) & ~3);
  3653. +    memcpy_toio(dev->mem_start, buf, (count + 3) & ~3);
  3654.      outw(option_reg, ioaddr + HPP_OPTION);
  3655.  
  3656.      return;
  3657. diff -u --recursive --new-file v1.3.30/linux/drivers/net/hp.c linux/drivers/net/hp.c
  3658. --- v1.3.30/linux/drivers/net/hp.c    Tue Aug 15 20:39:03 1995
  3659. +++ linux/drivers/net/hp.c    Sun Oct  1 19:18:58 1995
  3660. @@ -60,10 +60,13 @@
  3661.  int hp_probe1(struct device *dev, int ioaddr);
  3662.  
  3663.  static void hp_reset_8390(struct device *dev);
  3664. -static int hp_block_input(struct device *dev, int count,
  3665. -                          char *buf, int ring_offset);
  3666. +static void hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  3667. +                    int ring_page);
  3668. +static void hp_block_input(struct device *dev, int count,
  3669. +                    struct sk_buff *skb , int ring_offset);
  3670.  static void hp_block_output(struct device *dev, int count,
  3671.                              const unsigned char *buf, const start_page);
  3672. +
  3673.  static void hp_init_card(struct device *dev);
  3674.  
  3675.  /* The map from IRQ number to HP_CONFIGURE register setting. */
  3676. @@ -184,6 +187,7 @@
  3677.      ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
  3678.  
  3679.      ei_status.reset_8390 = &hp_reset_8390;
  3680. +    ei_status.get_8390_hdr = &hp_get_8390_hdr;
  3681.      ei_status.block_input = &hp_block_input;
  3682.      ei_status.block_output = &hp_block_output;
  3683.      hp_init_card(dev);
  3684. @@ -214,17 +218,40 @@
  3685.      return;
  3686.  }
  3687.  
  3688. -/* Block input and output, similar to the Crynwr packet driver.     If you
  3689. +static void
  3690. +hp_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  3691. +{
  3692. +    int nic_base = dev->base_addr;
  3693. +    int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
  3694. +
  3695. +    outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
  3696. +    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
  3697. +    outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
  3698. +    outb_p(0, nic_base + EN0_RCNTHI);
  3699. +    outb_p(0, nic_base + EN0_RSARLO);    /* On page boundary */
  3700. +    outb_p(ring_page, nic_base + EN0_RSARHI);
  3701. +    outb_p(E8390_RREAD+E8390_START, nic_base);
  3702. +
  3703. +    if (ei_status.word16) 
  3704. +      insw(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
  3705. +    else 
  3706. +      insb(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
  3707. +
  3708. +    outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
  3709. +}
  3710. +    
  3711. +/* Block input and output, similar to the Crynwr packet driver. If you are
  3712.     porting to a new ethercard look at the packet driver source for hints.
  3713.     The HP LAN doesn't use shared memory -- we put the packet
  3714.     out through the "remote DMA" dataport. */
  3715.  
  3716. -static int
  3717. -hp_block_input(struct device *dev, int count, char *buf, int ring_offset)
  3718. +static void
  3719. +hp_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  3720.  {
  3721.      int nic_base = dev->base_addr;
  3722.      int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
  3723.      int xfer_count = count;
  3724. +    char *buf = skb->data;
  3725.  
  3726.      outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
  3727.      outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
  3728. @@ -251,7 +278,6 @@
  3729.                 dev->name, ring_offset + xfer_count, addr);
  3730.      }
  3731.      outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
  3732. -    return ring_offset + count;
  3733.  }
  3734.  
  3735.  static void
  3736. diff -u --recursive --new-file v1.3.30/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
  3737. --- v1.3.30/linux/drivers/net/loopback.c    Sat Sep  9 15:26:52 1995
  3738. +++ linux/drivers/net/loopback.c    Wed Oct  4 08:15:11 1995
  3739. @@ -14,6 +14,7 @@
  3740.   *        Alan Cox    :    Fixed oddments for NET3.014
  3741.   *        Alan Cox    :    Rejig for NET3.029 snap #3
  3742.   *        Alan Cox    :     Fixed NET3.029 bugs and sped up
  3743. + *        Larry McVoy    :    Tiny tweak to double performance
  3744.   *
  3745.   *        This program is free software; you can redistribute it and/or
  3746.   *        modify it under the terms of the GNU General Public License
  3747. diff -u --recursive --new-file v1.3.30/linux/drivers/net/ne.c linux/drivers/net/ne.c
  3748. --- v1.3.30/linux/drivers/net/ne.c    Tue Aug 15 20:39:03 1995
  3749. +++ linux/drivers/net/ne.c    Sun Oct  1 19:18:58 1995
  3750. @@ -73,6 +73,7 @@
  3751.      {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
  3752.      {"NN1000", "NN2000",  {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
  3753.      {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}},  /* Outlaw 4-Dimension cards. */
  3754. +    {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
  3755.      {0,}
  3756.  };
  3757.  #endif
  3758. @@ -92,8 +93,10 @@
  3759.  static int ne_probe1(struct device *dev, int ioaddr);
  3760.  
  3761.  static void ne_reset_8390(struct device *dev);
  3762. -static int ne_block_input(struct device *dev, int count,
  3763. -              char *buf, int ring_offset);
  3764. +static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  3765. +              int ring_page);
  3766. +static void ne_block_input(struct device *dev, int count,
  3767. +              struct sk_buff *skb, int ring_offset);
  3768.  static void ne_block_output(struct device *dev, const int count,
  3769.          const unsigned char *buf, const int start_page);
  3770.  
  3771. @@ -181,14 +184,12 @@
  3772.      /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
  3773.      outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
  3774.  
  3775. -    /* wait 20 ms for the dust to settle. */
  3776. -    while (jiffies - reset_start_time < 2*HZ/100) 
  3777. -        barrier();
  3778. -
  3779. -    if ((inb_p(ioaddr+EN0_ISR) & ENISR_RESET) == 0) {
  3780. -        printk(" not found (no reset ack).\n");
  3781. -        return ENODEV;
  3782. -    }
  3783. +    while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
  3784. +        if (jiffies - reset_start_time > 2*HZ/100) {
  3785. +            printk(" not found (no reset ack).\n");
  3786. +            return ENODEV;
  3787. +        }
  3788. +
  3789.      outb_p(0xff, ioaddr + EN0_ISR);        /* Ack all intr. */
  3790.      }
  3791.  
  3792. @@ -338,6 +339,7 @@
  3793.      ei_status.reset_8390 = &ne_reset_8390;
  3794.      ei_status.block_input = &ne_block_input;
  3795.      ei_status.block_output = &ne_block_output;
  3796. +    ei_status.get_8390_hdr = &ne_get_8390_hdr;
  3797.      NS8390_init(dev, 0);
  3798.      return 0;
  3799.  }
  3800. @@ -366,27 +368,63 @@
  3801.      outb_p(ENISR_RESET, NE_BASE + EN0_ISR);    /* Ack intr. */
  3802.  }
  3803.  
  3804. +/* Grab the 8390 specific header. Similar to the block_input routine, but
  3805. +   we don't need to be concerned with ring wrap as the header will be at
  3806. +   the start of a page, so we optimize accordingly. */
  3807. +
  3808. +static void
  3809. +ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  3810. +{
  3811. +
  3812. +    int nic_base = dev->base_addr;
  3813. +
  3814. +    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
  3815. +    if (ei_status.dmaing) {
  3816. +    printk("%s: DMAing conflict in ne_get_8390_hdr "
  3817. +       "[DMAstat:%d][irqlock:%d][intr:%d].\n",
  3818. +       dev->name, ei_status.dmaing, ei_status.irqlock,
  3819. +       dev->interrupt);
  3820. +    return;
  3821. +    }
  3822. +
  3823. +    ei_status.dmaing |= 0x01;
  3824. +    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
  3825. +    outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
  3826. +    outb_p(0, nic_base + EN0_RCNTHI);
  3827. +    outb_p(0, nic_base + EN0_RSARLO);        /* On page boundary */
  3828. +    outb_p(ring_page, nic_base + EN0_RSARHI);
  3829. +    outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
  3830. +
  3831. +    if (ei_status.word16)
  3832. +    insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
  3833. +    else
  3834. +    insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
  3835. +
  3836. +    outb_p(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
  3837. +    ei_status.dmaing &= ~0x01;
  3838. +}
  3839. +
  3840.  /* Block input and output, similar to the Crynwr packet driver.  If you
  3841.     are porting to a new ethercard, look at the packet driver source for hints.
  3842. -   The NEx000 doesn't share it on-board packet memory -- you have to put
  3843. +   The NEx000 doesn't share the on-board packet memory -- you have to put
  3844.     the packet out through the "remote DMA" dataport using outb. */
  3845.  
  3846. -static int
  3847. -ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
  3848. +static void
  3849. +ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  3850.  {
  3851. -    int nic_base = dev->base_addr;
  3852.  #ifdef CONFIG_NE_SANITY
  3853.      int xfer_count = count;
  3854.  #endif
  3855. +    int nic_base = dev->base_addr;
  3856. +    char *buf = skb->data;
  3857.  
  3858.      /* This *shouldn't* happen. If it does, it's the last thing you'll see */
  3859.      if (ei_status.dmaing) {
  3860. -    if (ei_debug > 0)
  3861. -        printk("%s: DMAing conflict in ne_block_input "
  3862. -           "[DMAstat:%d][irqlock:%d][intr:%d].\n",
  3863. -           dev->name, ei_status.dmaing, ei_status.irqlock,
  3864. -           dev->interrupt);
  3865. -    return 0;
  3866. +    printk("%s: DMAing conflict in ne_block_input "
  3867. +       "[DMAstat:%d][irqlock:%d][intr:%d].\n",
  3868. +       dev->name, ei_status.dmaing, ei_status.irqlock,
  3869. +       dev->interrupt);
  3870. +    return;
  3871.      }
  3872.      ei_status.dmaing |= 0x01;
  3873.      outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
  3874. @@ -431,7 +469,6 @@
  3875.  #endif
  3876.      outb_p(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
  3877.      ei_status.dmaing &= ~0x01;
  3878. -    return ring_offset + count;
  3879.  }
  3880.  
  3881.  static void
  3882. @@ -452,11 +489,10 @@
  3883.  
  3884.      /* This *shouldn't* happen. If it does, it's the last thing you'll see */
  3885.      if (ei_status.dmaing) {
  3886. -    if (ei_debug > 0)
  3887. -        printk("%s: DMAing conflict in ne_block_output."
  3888. -           "[DMAstat:%d][irqlock:%d][intr:%d]\n",
  3889. -           dev->name, ei_status.dmaing, ei_status.irqlock,
  3890. -           dev->interrupt);
  3891. +    printk("%s: DMAing conflict in ne_block_output."
  3892. +       "[DMAstat:%d][irqlock:%d][intr:%d]\n",
  3893. +       dev->name, ei_status.dmaing, ei_status.irqlock,
  3894. +       dev->interrupt);
  3895.      return;
  3896.      }
  3897.      ei_status.dmaing |= 0x01;
  3898. diff -u --recursive --new-file v1.3.30/linux/drivers/net/plip.c linux/drivers/net/plip.c
  3899. --- v1.3.30/linux/drivers/net/plip.c    Mon Sep 18 14:53:54 1995
  3900. +++ linux/drivers/net/plip.c    Tue Oct  3 08:38:10 1995
  3901. @@ -1,4 +1,4 @@
  3902. -/* $Id: plip.c,v 1.14 1995/09/18 04:57:24 gniibe Exp $ */
  3903. +/* $Id: plip.c,v 1.15 1995/10/03 01:47:09 gniibe Exp $ */
  3904.  /* PLIP: A parallel port "network" driver for Linux. */
  3905.  /* This driver is for parallel port with 5-bit cable (LapLink (R) cable). */
  3906.  /*
  3907. @@ -24,6 +24,8 @@
  3908.   *        Niibe Yutaka
  3909.   *          - Module initialization.  You can specify I/O addr and IRQ:
  3910.   *            # insmod plip.o io=0x3bc irq=7
  3911. + *          - MTU fix.
  3912. + *          - Make sure other end is OK, before sending a packet.
  3913.   *
  3914.   *        This program is free software; you can redistribute it and/or
  3915.   *        modify it under the terms of the GNU General Public License
  3916. @@ -45,6 +47,10 @@
  3917.   *     So, this PLIP can't communicate the PLIP of Linux v1.0.
  3918.   */
  3919.  
  3920. +/*
  3921. + *     To use with DOS box, please do (Turn on ARP switch):
  3922. + *    # ifconfig plip[0-2] arp
  3923. + */
  3924.  static const char *version = "NET3 PLIP version 2.1 gniibe@mri.co.jp\n";
  3925.  
  3926.  /*
  3927. @@ -534,7 +540,8 @@
  3928.          if (plip_receive(nibble_timeout, status_addr,
  3929.                   &rcv->nibble, &rcv->length.b.msb))
  3930.              return TIMEOUT;
  3931. -        if (rcv->length.h > dev->mtu || rcv->length.h < 8) {
  3932. +        if (rcv->length.h > dev->mtu + dev->hard_header_len
  3933. +            || rcv->length.h < 8) {
  3934.              printk("%s: bogus packet size %d.\n", dev->name, rcv->length.h);
  3935.              return ERROR;
  3936.          }
  3937. @@ -672,6 +679,9 @@
  3938.  
  3939.      switch (snd->state) {
  3940.      case PLIP_PK_TRIGGER:
  3941. +        if ((inb(PAR_STATUS(dev)) & 0xf8) != 0x80)
  3942. +            return TIMEOUT;
  3943. +
  3944.          /* Trigger remote rx interrupt. */
  3945.          outb(0x08, data_addr);
  3946.          cx = nl->trigger;
  3947. @@ -894,7 +904,7 @@
  3948.          return 1;
  3949.      }
  3950.  
  3951. -    if (skb->len > dev->mtu) {
  3952. +    if (skb->len > dev->mtu + dev->hard_header_len) {
  3953.          printk("%s: packet too big, %d.\n", dev->name, (int)skb->len);
  3954.          dev->tbusy = 0;
  3955.          return 0;
  3956. diff -u --recursive --new-file v1.3.30/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
  3957. --- v1.3.30/linux/drivers/net/ppp.c    Mon Sep 18 14:53:54 1995
  3958. +++ linux/drivers/net/ppp.c    Fri Sep 29 07:07:57 1995
  3959. @@ -746,7 +746,7 @@
  3960.      ppp->stats.sbytes += actual;
  3961.      if (actual == count) {
  3962.          ppp->xtail = 0;
  3963. -        tty->flags &= ~TTY_DO_WRITE_WAKEUP;
  3964. +        tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
  3965.  
  3966.          ppp_output_done(ppp);
  3967.      } else {
  3968. diff -u --recursive --new-file v1.3.30/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
  3969. --- v1.3.30/linux/drivers/net/smc-ultra.c    Tue Aug 15 20:39:03 1995
  3970. +++ linux/drivers/net/smc-ultra.c    Sun Oct  1 19:18:58 1995
  3971. @@ -66,8 +66,10 @@
  3972.  
  3973.  static int ultra_open(struct device *dev);
  3974.  static void ultra_reset_8390(struct device *dev);
  3975. -static int ultra_block_input(struct device *dev, int count,
  3976. -                          char *buf, int ring_offset);
  3977. +static void ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, 
  3978. +                        int ring_page);
  3979. +static void ultra_block_input(struct device *dev, int count,
  3980. +                          struct sk_buff *skb, int ring_offset);
  3981.  static void ultra_block_output(struct device *dev, int count,
  3982.                              const unsigned char *buf, const start_page);
  3983.  static int ultra_close_card(struct device *dev);
  3984. @@ -211,6 +213,7 @@
  3985.      ei_status.reset_8390 = &ultra_reset_8390;
  3986.      ei_status.block_input = &ultra_block_input;
  3987.      ei_status.block_output = &ultra_block_output;
  3988. +    ei_status.get_8390_hdr = &ultra_get_8390_hdr;
  3989.      dev->open = &ultra_open;
  3990.      dev->stop = &ultra_close_card;
  3991.      NS8390_init(dev, 0);
  3992. @@ -253,44 +256,56 @@
  3993.      return;
  3994.  }
  3995.  
  3996. +/* Grab the 8390 specific header. Similar to the block_input routine, but
  3997. +   we don't need to be concerned with ring wrap as the header will be at
  3998. +   the start of a page, so we optimize accordingly. */
  3999. +
  4000. +static void
  4001. +ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  4002. +{
  4003. +
  4004. +    unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
  4005. +
  4006. +    outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);    /* shmem on */
  4007. +    memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
  4008. +    outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
  4009. +}
  4010. +
  4011.  /* Block input and output are easy on shared memory ethercards, the only
  4012.     complication is when the ring buffer wraps. */
  4013.  
  4014. -static int
  4015. -ultra_block_input(struct device *dev, int count, char *buf, int ring_offset)
  4016. +static void
  4017. +ultra_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  4018.  {
  4019. -    void *xfer_start = (void *)(dev->mem_start + ring_offset
  4020. -                                - (START_PG<<8));
  4021. +    unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8);
  4022.  
  4023.      /* Enable shared memory. */
  4024.      outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
  4025.  
  4026. -    if (xfer_start + count > (void*) dev->rmem_end) {
  4027. +    if (xfer_start + count > dev->rmem_end) {
  4028.          /* We must wrap the input move. */
  4029. -        int semi_count = (void*)dev->rmem_end - xfer_start;
  4030. -        memcpy(buf, xfer_start, semi_count);
  4031. +        int semi_count = dev->rmem_end - xfer_start;
  4032. +        memcpy_fromio(skb->data, xfer_start, semi_count);
  4033.          count -= semi_count;
  4034. -        memcpy(buf + semi_count, (char *)dev->rmem_start, count);
  4035. -        outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
  4036. -        return dev->rmem_start + count;
  4037. +        memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
  4038. +    } else {
  4039. +        /* Packet is in one chunk -- we can copy + cksum. */
  4040. +        eth_io_copy_and_sum(skb, xfer_start, count, 0);
  4041.      }
  4042. -    memcpy(buf, xfer_start, count);
  4043.  
  4044. -    outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
  4045. -    return ring_offset + count;
  4046. +    outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);    /* Disable memory. */
  4047.  }
  4048.  
  4049.  static void
  4050.  ultra_block_output(struct device *dev, int count, const unsigned char *buf,
  4051.                  int start_page)
  4052.  {
  4053. -    unsigned char *shmem
  4054. -        = (unsigned char *)dev->mem_start + ((start_page - START_PG)<<8);
  4055. +    unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8);
  4056.  
  4057.      /* Enable shared memory. */
  4058.      outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
  4059.  
  4060. -    memcpy(shmem, buf, count);
  4061. +    memcpy_toio(shmem, buf, count);
  4062.  
  4063.      outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
  4064.  }
  4065. diff -u --recursive --new-file v1.3.30/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
  4066. --- v1.3.30/linux/drivers/net/tulip.c    Tue Aug 15 20:39:03 1995
  4067. +++ linux/drivers/net/tulip.c    Wed Oct  4 08:15:11 1995
  4068. @@ -696,7 +696,7 @@
  4069.      short ioaddr = dev->base_addr;
  4070.      int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
  4071.  
  4072. -    if (num_addrs > 15) {
  4073. +    if (num_addrs > 15 || num_addrs == -2) {
  4074.          /* Too many to filter perfectly -- accept all multicasts. */
  4075.          outl(csr6 | 0x0080, ioaddr + CSR6);
  4076.      } else if (num_addrs < 0) {            /* Set promiscuous. */
  4077. diff -u --recursive --new-file v1.3.30/linux/drivers/net/wd.c linux/drivers/net/wd.c
  4078. --- v1.3.30/linux/drivers/net/wd.c    Tue Aug 15 20:39:03 1995
  4079. +++ linux/drivers/net/wd.c    Sun Oct  1 19:18:58 1995
  4080. @@ -45,8 +45,10 @@
  4081.  
  4082.  static int wd_open(struct device *dev);
  4083.  static void wd_reset_8390(struct device *dev);
  4084. -static int wd_block_input(struct device *dev, int count,
  4085. -                          char *buf, int ring_offset);
  4086. +static void wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  4087. +                        int ring_page);
  4088. +static void wd_block_input(struct device *dev, int count,
  4089. +                          struct sk_buff *skb, int ring_offset);
  4090.  static void wd_block_output(struct device *dev, int count,
  4091.                              const unsigned char *buf, const start_page);
  4092.  static int wd_close_card(struct device *dev);
  4093. @@ -261,6 +263,7 @@
  4094.      ei_status.reset_8390 = &wd_reset_8390;
  4095.      ei_status.block_input = &wd_block_input;
  4096.      ei_status.block_output = &wd_block_output;
  4097. +    ei_status.get_8390_hdr = &wd_get_8390_hdr;
  4098.      dev->open = &wd_open;
  4099.      dev->stop = &wd_close_card;
  4100.      NS8390_init(dev, 0);
  4101. @@ -316,40 +319,50 @@
  4102.      return;
  4103.  }
  4104.  
  4105. +/* Grab the 8390 specific header. Similar to the block_input routine, but
  4106. +   we don't need to be concerned with ring wrap as the header will be at
  4107. +   the start of a page, so we optimize accordingly. */
  4108. +
  4109. +static void
  4110. +wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  4111. +{
  4112. +
  4113. +    int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
  4114. +    unsigned long hdr_start = dev->mem_start + ((ring_page - WD_START_PG)<<8);
  4115. +
  4116. +    /* We'll always get a 4 byte header read followed by a packet read, so
  4117. +       we enable 16 bit mode before the header, and disable after the body. */
  4118. +    if (ei_status.word16)
  4119. +        outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
  4120. +
  4121. +    memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
  4122. +}
  4123. +
  4124.  /* Block input and output are easy on shared memory ethercards, and trivial
  4125.     on the Western digital card where there is no choice of how to do it.
  4126.     The only complications are that the ring buffer wraps, and need to map
  4127.     switch between 8- and 16-bit modes. */
  4128.  
  4129. -static int
  4130. -wd_block_input(struct device *dev, int count, char *buf, int ring_offset)
  4131. +static void
  4132. +wd_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
  4133.  {
  4134.      int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
  4135. -    long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
  4136. -
  4137. -    /* We'll always get a 4 byte header read followed by a packet read, so
  4138. -       we enable 16 bit mode before the header, and disable after the body. */
  4139. -    if (count == 4) {
  4140. -        if (ei_status.word16)
  4141. -            outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
  4142. -        ((int*)buf)[0] = ((int*)xfer_start)[0];
  4143. -        return 0;
  4144. -    }
  4145. +    unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
  4146.  
  4147.      if (xfer_start + count > dev->rmem_end) {
  4148.          /* We must wrap the input move. */
  4149.          int semi_count = dev->rmem_end - xfer_start;
  4150. -        memcpy(buf, (char *)xfer_start, semi_count);
  4151. +        memcpy_fromio(skb->data, xfer_start, semi_count);
  4152.          count -= semi_count;
  4153. -        memcpy(buf + semi_count, (char *)dev->rmem_start, count);
  4154. -    } else
  4155. -        memcpy(buf, (char *)xfer_start, count);
  4156. +        memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
  4157. +    } else {
  4158. +        /* Packet is in one chunk -- we can copy + cksum. */
  4159. +        eth_io_copy_and_sum(skb, xfer_start, count, 0);
  4160. +    }
  4161.  
  4162.      /* Turn off 16 bit access so that reboot works.     ISA brain-damage */
  4163.      if (ei_status.word16)
  4164.          outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
  4165. -
  4166. -    return 0;
  4167.  }
  4168.  
  4169.  static void
  4170. @@ -363,10 +376,10 @@
  4171.      if (ei_status.word16) {
  4172.          /* Turn on and off 16 bit access so that reboot works. */
  4173.          outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
  4174. -        memcpy((char *)shmem, buf, count);
  4175. +        memcpy_toio(shmem, buf, count);
  4176.          outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
  4177.      } else
  4178. -        memcpy((char *)shmem, buf, count);
  4179. +        memcpy_toio(shmem, buf, count);
  4180.  }
  4181.  
  4182.  
  4183. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
  4184. --- v1.3.30/linux/drivers/scsi/53c7,8xx.c    Wed Sep 27 15:59:58 1995
  4185. +++ linux/drivers/scsi/53c7,8xx.c    Mon Oct  2 08:21:06 1995
  4186. @@ -1121,7 +1121,7 @@
  4187.       * hostdata structure rather than in the RELATIVE area of the 
  4188.       * SCRIPTS.
  4189.       */
  4190. -    
  4191. +
  4192.  
  4193.      patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp);
  4194.      patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr);
  4195. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
  4196. --- v1.3.30/linux/drivers/scsi/eata_dma.c    Mon Sep 25 12:26:22 1995
  4197. +++ linux/drivers/scsi/eata_dma.c    Fri Sep 29 09:27:28 1995
  4198. @@ -881,7 +881,7 @@
  4199.      }
  4200.      
  4201.      /* if gc->DMA_valid it must be an ISA HBA and we have to register it */
  4202. -    dma_channel = 0xff;
  4203. +    dma_channel = BUSMASTER;
  4204.      if (gc->DMA_valid) {
  4205.      if (request_dma(dma_channel = (8 - gc->DMA_channel) & 7, "eata_dma")) {
  4206.          printk("Unable to allocate DMA channel %d for ISA HBA at %#.4x.\n",
  4207. @@ -1025,8 +1025,9 @@
  4208.  
  4209.      hd->channel = gc->MAX_CHAN;        
  4210.      sh->max_channel = gc->MAX_CHAN; 
  4211. +    sh->unique_id = base;
  4212.      sh->base = (char *) base;
  4213. -    sh->io_port = (u16) base;
  4214. +    sh->io_port = base;
  4215.      sh->n_io_port = 9;
  4216.      sh->irq = gc->IRQ;
  4217.      sh->dma_channel = dma_channel;
  4218. @@ -1318,7 +1319,7 @@
  4219.             SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? 
  4220.             "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",
  4221.             (u32) HBA_ptr->base, HBA_ptr->irq);
  4222. -        if(HBA_ptr->dma_channel != 0xff)
  4223. +        if(HBA_ptr->dma_channel != BUSMASTER)
  4224.          printk("   %2x ", HBA_ptr->dma_channel);
  4225.          else
  4226.          printk("  %s", "BMST");
  4227. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c
  4228. --- v1.3.30/linux/drivers/scsi/eata_dma_proc.c    Mon Sep 25 12:26:22 1995
  4229. +++ linux/drivers/scsi/eata_dma_proc.c    Fri Sep 29 09:27:28 1995
  4230. @@ -90,6 +90,7 @@
  4231.      int      size, len = 0;
  4232.      off_t begin = 0;
  4233.      off_t pos = 0;
  4234. +    scd = NULL;
  4235.  
  4236.      HBA_ptr = first_HBA;
  4237.      for (i = 1; i <= registered_HBAs; i++) {
  4238. @@ -135,8 +136,8 @@
  4239.      len += size; 
  4240.      pos = begin + len;
  4241.      
  4242. -    if(SD(HBA_ptr)->bustype == IS_EISA) {
  4243. -    if (HBA_ptr->dma_channel == 0xff)
  4244. +    if(SD(HBA_ptr)->broken_INQUIRY == TRUE) {
  4245. +    if (HBA_ptr->dma_channel == BUSMASTER)
  4246.          size = sprintf(buffer + len, "DMA: BUSMASTER\n");
  4247.      else
  4248.          size = sprintf(buffer + len, "DMA: %d\n", HBA_ptr->dma_channel);
  4249. @@ -146,6 +147,7 @@
  4250.      size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) HBA_ptr->base);
  4251.      len += size; 
  4252.      pos = begin + len;
  4253. +
  4254.      size = sprintf(buffer + len, "Host Bus: EISA\n"); 
  4255.      len += size; 
  4256.      pos = begin + len;
  4257. @@ -456,6 +458,7 @@
  4258.          goto stop_output;
  4259.      }
  4260.  
  4261. +#if 0
  4262.      scd = scsi_devices;
  4263.      
  4264.      size = sprintf(buffer+len,"Attached devices: %s\n", (scd)?"":"none");
  4265. @@ -477,6 +480,7 @@
  4266.      }
  4267.      scd = scd->next;
  4268.      }
  4269. +#endif
  4270.      
  4271.   stop_output:
  4272.      DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len));
  4273. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/eata_generic.h linux/drivers/scsi/eata_generic.h
  4274. --- v1.3.30/linux/drivers/scsi/eata_generic.h    Tue Jul 18 16:28:58 1995
  4275. +++ linux/drivers/scsi/eata_generic.h    Fri Sep 29 09:27:28 1995
  4276. @@ -40,6 +40,9 @@
  4277.  
  4278.  #define BROKEN_INQUIRY    1
  4279.  
  4280. +#define BUSMASTER       0xff
  4281. +#define PIO             0xfe
  4282. +
  4283.  #define EATA_SIGNATURE    0x45415441     /* BIG ENDIAN coded "EATA" sig.     */
  4284.  #define EATA_CP_SIZE    44
  4285.  
  4286. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c
  4287. --- v1.3.30/linux/drivers/scsi/eata_pio.c    Mon Sep 25 12:26:22 1995
  4288. +++ linux/drivers/scsi/eata_pio.c    Fri Sep 29 09:27:29 1995
  4289. @@ -783,11 +783,12 @@
  4290.      SD(sh)->hostid=gc->scsi_id[3];
  4291.      SD(sh)->devflags=1<<gc->scsi_id[3];
  4292.      SD(sh)->moresupport=gc->MORE_support;
  4293. +    sh->unique_id = base;
  4294.      sh->base = (char *) base;
  4295. -    sh->io_port = (ushort) base;
  4296. +    sh->io_port = base;
  4297.      sh->n_io_port = 8;
  4298.      sh->irq = gc->IRQ;
  4299. -    sh->dma_channel = 0xfe;  /* PIO */
  4300. +    sh->dma_channel = PIO;
  4301.      sh->this_id = gc->scsi_id[3];
  4302.      sh->can_queue = 1;
  4303.      sh->cmd_per_lun = 1;
  4304. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
  4305. --- v1.3.30/linux/drivers/scsi/scsi_proc.c    Mon Sep 18 14:54:02 1995
  4306. +++ linux/drivers/scsi/scsi_proc.c    Fri Sep 29 09:27:29 1995
  4307. @@ -265,8 +265,8 @@
  4308.      int x, y = *size;
  4309.      
  4310.      y = sprintf(buffer + len, 
  4311. -            "Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
  4312. -            scd->channel, scd->id, scd->lun);
  4313. +            "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
  4314. +            scd->host->host_no, scd->channel, scd->id, scd->lun);
  4315.      for (x = 0; x < 8; x++) {
  4316.      if (scd->vendor[x] >= 0x20)
  4317.          y += sprintf(buffer + len + y, "%c", scd->vendor[x]);
  4318. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
  4319. --- v1.3.30/linux/drivers/scsi/sd.c    Mon Sep 18 14:54:03 1995
  4320. +++ linux/drivers/scsi/sd.c    Tue Oct  3 08:24:17 1995
  4321. @@ -1325,7 +1325,7 @@
  4322.           * Reset the blocksize for everything so that we can read
  4323.           * the partition table.
  4324.           */
  4325. -        blksize_size[MAJOR_NR][i] = 1024;
  4326. +        blksize_size[MAJOR_NR][minor] = 1024;
  4327.      };
  4328.      
  4329.  #ifdef MAYBE_REINIT
  4330. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
  4331. --- v1.3.30/linux/drivers/scsi/sr_ioctl.c    Mon Sep 18 14:54:03 1995
  4332. +++ linux/drivers/scsi/sr_ioctl.c    Sun Oct  1 19:51:44 1995
  4333. @@ -158,7 +158,31 @@
  4334.      result = do_ioctl(target, sr_cmd, NULL, 255);
  4335.      return result;
  4336.      }
  4337. +
  4338. +    case CDROMPLAYBLK:
  4339. +    {
  4340. +    struct cdrom_blk blk;
  4341. +
  4342. +        err = verify_area (VERIFY_READ, (void *) arg, sizeof (blk));
  4343. +        if (err) return err;
  4344. +
  4345. +    memcpy_fromfs(&blk, (void *) arg, sizeof(blk));
  4346.      
  4347. +    sr_cmd[0] = SCMD_PLAYAUDIO10;
  4348. +    sr_cmd[1] = scsi_CDs[target].device->lun << 5;
  4349. +    sr_cmd[2] = blk.from >> 24;
  4350. +    sr_cmd[3] = blk.from >> 16;
  4351. +    sr_cmd[4] = blk.from >> 8;
  4352. +    sr_cmd[5] = blk.from;
  4353. +    sr_cmd[6] = 0;
  4354. +    sr_cmd[7] = blk.len >> 8;
  4355. +    sr_cmd[8] = blk.len;
  4356. +    sr_cmd[9] = 0;
  4357. +    
  4358. +    result = do_ioctl(target, sr_cmd, NULL, 255);
  4359. +    return result;
  4360. +    }
  4361. +        
  4362.      case CDROMPLAYTRKIND:
  4363.      {
  4364.      struct cdrom_ti ti;
  4365. diff -u --recursive --new-file v1.3.30/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
  4366. --- v1.3.30/linux/drivers/scsi/st.c    Wed Sep 27 15:59:59 1995
  4367. +++ linux/drivers/scsi/st.c    Wed Oct  4 08:15:24 1995
  4368. @@ -11,7 +11,7 @@
  4369.    Copyright 1992, 1993, 1994, 1995 Kai Makisara
  4370.           email Kai.Makisara@metla.fi
  4371.  
  4372. -  Last modified: Mon Sep 25 19:52:16 1995 by root@kai.makisara.fi
  4373. +  Last modified: Sat Sep 30 15:54:57 1995 by root@kai.makisara.fi
  4374.    Some small formal changes - aeb, 950809
  4375.  */
  4376.  #ifdef MODULE
  4377. @@ -684,6 +684,8 @@
  4378.      if (!SCpnt)
  4379.        return;
  4380.  
  4381. +    SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
  4382. +
  4383.      if ((STp->buffer)->last_result_fatal != 0)
  4384.        printk("st%d: Error on write filemark.\n", dev);
  4385.      else {
  4386. @@ -693,7 +695,6 @@
  4387.        if (STp->two_fm)
  4388.          back_over_eof(STp);
  4389.      }
  4390. -    SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
  4391.        }
  4392.  
  4393.  #if DEBUG
  4394. @@ -972,7 +973,7 @@
  4395.             (STp->buffer)->writing,
  4396.             st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
  4397.      }
  4398. -    else
  4399. +    else if (SCpnt != NULL)
  4400.        SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
  4401.  
  4402.      STp->at_sm &= (total != 0);
  4403. @@ -1192,7 +1193,8 @@
  4404.        }
  4405.        else if (STp->eof != ST_NOEOF) {
  4406.      STp->eof_hit = 1;
  4407. -    SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
  4408. +    if (SCpnt != NULL)
  4409. +      SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
  4410.      if (total == 0 && STp->eof == ST_FM) {
  4411.        STp->eof = ST_NOEOF;
  4412.        STp->drv_block = 0;
  4413. @@ -1211,7 +1213,8 @@
  4414.  
  4415.      } /* for (total = 0; total < count; ) */
  4416.  
  4417. -    SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
  4418. +    if (SCpnt != NULL)
  4419. +      SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
  4420.  
  4421.      return total;
  4422.  }
  4423. @@ -1734,7 +1737,7 @@
  4424.  st_ioctl(struct inode * inode,struct file * file,
  4425.       unsigned int cmd_in, unsigned long arg)
  4426.  {
  4427. -   int i, cmd, result;
  4428. +   int i, cmd_nr, cmd_type, result;
  4429.     struct mtop mtc;
  4430.     struct mtpos mt_pos;
  4431.     unsigned char scmd[10];
  4432. @@ -1759,10 +1762,10 @@
  4433.         return scsi_ioctl(STp->device, cmd_in, (void *) arg);
  4434.       }
  4435.     
  4436. -   cmd = cmd_in & IOCCMD_MASK;
  4437. -   if (cmd == (MTIOCTOP & IOCCMD_MASK)) {
  4438. -
  4439. -     if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc))
  4440. +   cmd_type = _IOC_TYPE(cmd_in);
  4441. +   cmd_nr   = _IOC_NR(cmd_in);
  4442. +   if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
  4443. +     if (_IOC_SIZE(cmd_in) != sizeof(mtc))
  4444.         return (-EINVAL);
  4445.  
  4446.       i = verify_area(VERIFY_READ, (void *)arg, sizeof(mtc));
  4447. @@ -1816,9 +1819,9 @@
  4448.       else
  4449.         return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count);
  4450.     }
  4451. -   else if (cmd == (MTIOCGET & IOCCMD_MASK)) {
  4452. +   else if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
  4453.  
  4454. -     if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtget))
  4455. +     if (_IOC_SIZE(cmd_in) != sizeof(struct mtget))
  4456.         return (-EINVAL);
  4457.       i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtget));
  4458.       if (i)
  4459. @@ -1869,14 +1872,14 @@
  4460.       (STp->mt_status)->mt_erreg = 0;  /* Clear after read */
  4461.       return 0;
  4462.     }
  4463. -   else if (cmd == (MTIOCPOS & IOCCMD_MASK)) {
  4464. +   else if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
  4465.       if (STp->ready != ST_READY)
  4466.         return (-EIO);
  4467.  #if DEBUG
  4468.       if (debugging)
  4469.         printk("st%d: get tape position.\n", dev);
  4470.  #endif
  4471. -     if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtpos))
  4472. +     if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos))
  4473.         return (-EINVAL);
  4474.  
  4475.       i = flush_buffer(inode, file, 0);
  4476. diff -u --recursive --new-file v1.3.30/linux/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c
  4477. --- v1.3.30/linux/drivers/sound/sound_switch.c    Mon Aug 28 14:52:21 1995
  4478. +++ linux/drivers/sound/sound_switch.c    Sun Oct  1 10:00:52 1995
  4479. @@ -58,9 +58,7 @@
  4480.  {
  4481.    int             l;
  4482.  
  4483. -  for (l = 0; l < 256, s[l]; l++);    /*
  4484. -                     * l=strlen(s);
  4485. -                     */
  4486. +  l = strnlen(s, 256);
  4487.  
  4488.    if (status_len + l >= 4000)
  4489.      return 0;
  4490. diff -u --recursive --new-file v1.3.30/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
  4491. --- v1.3.30/linux/fs/binfmt_elf.c    Mon Sep 25 12:26:22 1995
  4492. +++ linux/fs/binfmt_elf.c    Wed Oct  4 08:11:50 1995
  4493. @@ -61,9 +61,9 @@
  4494.  
  4495.  struct linux_binfmt elf_format = {
  4496.  #ifndef MODULE
  4497. -    NULL, NULL, load_elf_binary, load_elf_library, aout_core_dump
  4498. +    NULL, NULL, load_elf_binary, load_elf_library, elf_core_dump
  4499.  #else
  4500. -    NULL, &mod_use_count_, load_elf_binary, load_elf_library, aout_core_dump
  4501. +    NULL, &mod_use_count_, load_elf_binary, load_elf_library, elf_core_dump
  4502.  #endif
  4503.  };
  4504.  
  4505. diff -u --recursive --new-file v1.3.30/linux/fs/ext2/super.c linux/fs/ext2/super.c
  4506. --- v1.3.30/linux/fs/ext2/super.c    Mon Sep 18 14:54:05 1995
  4507. +++ linux/fs/ext2/super.c    Mon Oct  2 14:32:53 1995
  4508. @@ -647,7 +647,7 @@
  4509.      /*
  4510.       * Allow the "check" option to be passed as a remount option.
  4511.       */
  4512. -    set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
  4513. +    set_opt (new_mount_opt, CHECK_NORMAL);
  4514.      if (!parse_options (data, &tmp, &resuid, &resgid,
  4515.                  &new_mount_opt))
  4516.          return -EINVAL;
  4517. diff -u --recursive --new-file v1.3.30/linux/fs/read_write.c linux/fs/read_write.c
  4518. --- v1.3.30/linux/fs/read_write.c    Tue Jun 27 14:11:44 1995
  4519. +++ linux/fs/read_write.c    Sat Sep 30 10:59:23 1995
  4520. @@ -10,6 +10,7 @@
  4521.  #include <linux/kernel.h>
  4522.  #include <linux/sched.h>
  4523.  #include <linux/mm.h>
  4524. +#include <linux/uio.h>
  4525.  
  4526.  #include <asm/segment.h>
  4527.  
  4528. @@ -148,4 +149,93 @@
  4529.          notify_change(inode, &newattrs);
  4530.      }
  4531.      return written;
  4532. +}
  4533. +
  4534. +/*
  4535. + * OSF/1 (and SunOS) readv/writev emulation.
  4536. + *
  4537. + * NOTE! This is not really the way it should be done,
  4538. + * but it should be good enough for TCP connections,
  4539. + * notably X11 ;-)
  4540. + */
  4541. +asmlinkage int sys_readv(unsigned long fd, const struct iovec * vector, long count)
  4542. +{
  4543. +    int retval;
  4544. +    struct file * file;
  4545. +    struct inode * inode;
  4546. +
  4547. +    if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
  4548. +        return -EBADF;
  4549. +    if (!(file->f_mode & 1))
  4550. +        return -EBADF;
  4551. +    if (!file->f_op || !file->f_op->read)
  4552. +        return -EINVAL;
  4553. +    if (!count)
  4554. +        return 0;
  4555. +    retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
  4556. +    if (retval)
  4557. +        return retval;
  4558. +
  4559. +    while (count > 0) {
  4560. +        void * base;
  4561. +        int len, nr;
  4562. +
  4563. +        base = get_user(&vector->iov_base);
  4564. +        len = get_user(&vector->iov_len);
  4565. +        vector++;
  4566. +        count--;
  4567. +        nr = verify_area(VERIFY_WRITE, base, len);
  4568. +        if (!nr)
  4569. +            nr = file->f_op->read(inode, file, base, len);
  4570. +        if (nr < 0) {
  4571. +            if (retval)
  4572. +                return retval;
  4573. +            return nr;
  4574. +        }
  4575. +        retval += nr;
  4576. +        if (nr != len)
  4577. +            break;
  4578. +    }
  4579. +    return retval;
  4580. +}
  4581. +
  4582. +asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count)
  4583. +{
  4584. +    int retval;
  4585. +    struct file * file;
  4586. +    struct inode * inode;
  4587. +
  4588. +    if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
  4589. +        return -EBADF;
  4590. +    if (!(file->f_mode & 2))
  4591. +        return -EBADF;
  4592. +    if (!file->f_op || !file->f_op->write)
  4593. +        return -EINVAL;
  4594. +    if (!count)
  4595. +        return 0;
  4596. +    retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
  4597. +    if (retval)
  4598. +        return retval;
  4599. +
  4600. +    while (count > 0) {
  4601. +        void * base;
  4602. +        int len, nr;
  4603. +
  4604. +        base = get_user(&vector->iov_base);
  4605. +        len = get_user(&vector->iov_len);
  4606. +        vector++;
  4607. +        count--;
  4608. +        nr = verify_area(VERIFY_READ, base, len);
  4609. +        if (!nr)
  4610. +            nr = file->f_op->write(inode, file, base, len);
  4611. +        if (nr < 0) {
  4612. +            if (retval)
  4613. +                return retval;
  4614. +            return nr;
  4615. +        }
  4616. +        retval += nr;
  4617. +        if (nr != len)
  4618. +            break;
  4619. +    }
  4620. +    return retval;
  4621.  }
  4622. diff -u --recursive --new-file v1.3.30/linux/include/asm-alpha/checksum.h linux/include/asm-alpha/checksum.h
  4623. --- v1.3.30/linux/include/asm-alpha/checksum.h    Wed Aug  2 13:21:16 1995
  4624. +++ linux/include/asm-alpha/checksum.h    Tue Oct  3 12:18:54 1995
  4625. @@ -55,4 +55,15 @@
  4626.  
  4627.  extern unsigned short ip_compute_csum(unsigned char * buff, int len);
  4628.  
  4629. +/*
  4630. + *    Fold a partial checksum without adding pseudo headers
  4631. + */
  4632. +
  4633. +static inline unsigned short csum_fold(unsigned int sum)
  4634. +{
  4635. +    sum = (sum & 0xffff) + (sum >> 16);
  4636. +    sum = (sum & 0xffff) + (sum >> 16);
  4637. +    return ~sum;
  4638. +}
  4639. +
  4640.  #endif
  4641. diff -u --recursive --new-file v1.3.30/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
  4642. --- v1.3.30/linux/include/asm-alpha/io.h    Sun Sep  3 12:27:01 1995
  4643. +++ linux/include/asm-alpha/io.h    Sun Oct  1 19:18:58 1995
  4644. @@ -127,6 +127,14 @@
  4645.  #define memcpy_fromio(to,from,len)    (memcpy_fromio)((to),(unsigned long)(from),(len))
  4646.  #define memcpy_toio(to,from,len)    (memcpy_toio)((unsigned long)(to),(from),(len))
  4647.  
  4648. +/*
  4649. + * XXX - We don't have csum_partial_copy_fromio() yet, so we cheat here and 
  4650. + * just copy it. The net code will then do the checksum later. Presently 
  4651. + * only used by some shared memory 8390 ethernet cards anyway.
  4652. + */
  4653. +
  4654. +#define eth_io_copy_and_sum(skb,src,len,unused)    memcpy_fromio((skb)->data,(src),(len))
  4655. +
  4656.  #endif /* __KERNEL__ */
  4657.  
  4658.  #endif
  4659. diff -u --recursive --new-file v1.3.30/linux/include/asm-alpha/param.h linux/include/asm-alpha/param.h
  4660. --- v1.3.30/linux/include/asm-alpha/param.h    Fri Jun  2 13:51:17 1995
  4661. +++ linux/include/asm-alpha/param.h    Mon Oct  2 08:21:06 1995
  4662. @@ -1,8 +1,15 @@
  4663.  #ifndef _ASMAXP_PARAM_H
  4664.  #define _ASMAXP_PARAM_H
  4665.  
  4666. +#include <linux/config.h>
  4667. +
  4668.  #ifndef HZ
  4669. -#define HZ 1024
  4670. +# if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P) || \
  4671. +     defined(CONFIG_ALPHA_EB64) || defined(CONFIG_ALPHA_EB64P)
  4672. +#  define HZ     977    /* Evaluation Boards seem to be a little odd */
  4673. +# else
  4674. +#  define HZ    1024    /* normal value for Alpha systems */
  4675. +# endif
  4676.  #endif
  4677.  
  4678.  #define EXEC_PAGESIZE    8192
  4679. diff -u --recursive --new-file v1.3.30/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
  4680. --- v1.3.30/linux/include/asm-alpha/unistd.h    Wed Sep 13 12:45:32 1995
  4681. +++ linux/include/asm-alpha/unistd.h    Sat Sep 30 18:04:05 1995
  4682. @@ -77,6 +77,8 @@
  4683.  #define __NR_gettimeofday    116
  4684.  #define __NR_getrusage        117
  4685.  #define __NR_getsockopt        118
  4686. +#define __NR_readv        120
  4687. +#define __NR_writev        121
  4688.  #define __NR_settimeofday    122
  4689.  #define __NR_fchown        123
  4690.  #define __NR_fchmod        124
  4691. @@ -126,7 +128,7 @@
  4692.  #define __NR_syslog        310
  4693.  #define __NR_reboot        311
  4694.  #define __NR_clone        312
  4695. -
  4696. +#define __NR_uselib        313
  4697.  
  4698.  #ifdef __LIBRARY__
  4699.  
  4700. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h
  4701. --- v1.3.30/linux/include/asm-i386/bitops.h    Mon Jul 31 15:59:02 1995
  4702. +++ linux/include/asm-i386/bitops.h    Tue Oct  3 12:22:10 1995
  4703. @@ -13,6 +13,14 @@
  4704.   * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  4705.   */
  4706.  
  4707. +#include <linux/config.h>
  4708. +
  4709. +#ifdef CONFIG_SMP
  4710. +#define LOCK_PREFIX "lock ; "
  4711. +#else
  4712. +#define LOCK_PREFIX ""
  4713. +#endif
  4714. +
  4715.  /*
  4716.   * Some hacks to defeat gcc over-optimizations..
  4717.   */
  4718. @@ -23,7 +31,8 @@
  4719.  {
  4720.      int oldbit;
  4721.  
  4722. -    __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
  4723. +    __asm__ __volatile__(LOCK_PREFIX
  4724. +        "btsl %2,%1\n\tsbbl %0,%0"
  4725.          :"=r" (oldbit),"=m" (ADDR)
  4726.          :"ir" (nr));
  4727.      return oldbit;
  4728. @@ -33,7 +42,8 @@
  4729.  {
  4730.      int oldbit;
  4731.  
  4732. -    __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
  4733. +    __asm__ __volatile__(LOCK_PREFIX
  4734. +        "btrl %2,%1\n\tsbbl %0,%0"
  4735.          :"=r" (oldbit),"=m" (ADDR)
  4736.          :"ir" (nr));
  4737.      return oldbit;
  4738. @@ -43,7 +53,8 @@
  4739.  {
  4740.      int oldbit;
  4741.  
  4742. -    __asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
  4743. +    __asm__ __volatile__(LOCK_PREFIX
  4744. +        "btcl %2,%1\n\tsbbl %0,%0"
  4745.          :"=r" (oldbit),"=m" (ADDR)
  4746.          :"ir" (nr));
  4747.      return oldbit;
  4748. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/checksum.h linux/include/asm-i386/checksum.h
  4749. --- v1.3.30/linux/include/asm-i386/checksum.h    Wed Sep 13 12:45:32 1995
  4750. +++ linux/include/asm-i386/checksum.h    Tue Oct  3 11:45:59 1995
  4751. @@ -103,20 +103,17 @@
  4752.   *    Fold a partial checksum without adding pseudo headers
  4753.   */
  4754.  
  4755. -static inline unsigned short int csum_fold(unsigned int sum)
  4756. +static inline unsigned int csum_fold(unsigned int sum)
  4757.  {
  4758. -     __asm__("
  4759. -         movl %0, %1
  4760. -         shrl $16, %1
  4761. -         addw %w1, %w0
  4762. -         adcl $0, %0
  4763. -         notl %0
  4764. -         "
  4765. -         : "=&r" (sum)
  4766. -         : "0" (sum)
  4767. -     );
  4768. -     return sum;
  4769. - }
  4770. +    __asm__("
  4771. +        addl %1, %0
  4772. +        adcl $0xffff, %0
  4773. +        "
  4774. +        : "=r" (sum)
  4775. +        : "r" (sum << 16), "0" (sum & 0xffff0000)
  4776. +    );
  4777. +    return (~sum) >> 16;
  4778. +}
  4779.   
  4780.  /*
  4781.   * this routine is used for miscellaneous IP-like checksums, mainly
  4782. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/delay.h linux/include/asm-i386/delay.h
  4783. --- v1.3.30/linux/include/asm-i386/delay.h    Wed Dec 14 14:18:14 1994
  4784. +++ linux/include/asm-i386/delay.h    Mon Oct  2 14:25:10 1995
  4785. @@ -6,6 +6,10 @@
  4786.   *
  4787.   * Delay routines, using a pre-computed "loops_per_second" value.
  4788.   */
  4789. +#ifdef CONFIG_SMP
  4790. +#include <asm/smp.h>
  4791. +#endif 
  4792.  
  4793.  extern __inline__ void __delay(int loops)
  4794.  {
  4795. @@ -27,8 +31,13 @@
  4796.      usecs *= 0x000010c6;        /* 2**32 / 1000000 */
  4797.      __asm__("mull %0"
  4798.          :"=d" (usecs)
  4799. +#ifdef CONFIG_SMP
  4800. +        :"a" (usecs),"0" (cpu_data[smp_processor_id()].udelay_val)
  4801. +#else
  4802.          :"a" (usecs),"0" (loops_per_sec)
  4803. +#endif
  4804.          :"ax");
  4805. +        
  4806.      __delay(usecs);
  4807.  }
  4808.  
  4809. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
  4810. --- v1.3.30/linux/include/asm-i386/io.h    Sun Sep  3 16:12:49 1995
  4811. +++ linux/include/asm-i386/io.h    Sun Oct  1 19:18:58 1995
  4812. @@ -78,6 +78,12 @@
  4813.  #define memcpy_toio(a,b,c)    memcpy((void *)(a),(b),(c))
  4814.  
  4815.  /*
  4816. + * Again, i386 does not require mem IO specific function.
  4817. + */
  4818. +
  4819. +#define eth_io_copy_and_sum(a,b,c,d)    eth_copy_and_sum((a),(void *)(b),(c),(d))
  4820. +
  4821. +/*
  4822.   * Talk about misusing macros..
  4823.   */
  4824.  
  4825. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/irq.h linux/include/asm-i386/irq.h
  4826. --- v1.3.30/linux/include/asm-i386/irq.h    Mon Sep 18 14:54:09 1995
  4827. +++ linux/include/asm-i386/irq.h    Mon Oct  2 14:25:11 1995
  4828. @@ -5,6 +5,8 @@
  4829.   *    linux/include/asm/irq.h
  4830.   *
  4831.   *    (C) 1992, 1993 Linus Torvalds
  4832. + *
  4833. + *    IRQ/IPI changes taken from work by Thomas Radke <tomsoft@informatik.tu-chemnitz.de>
  4834.   */
  4835.  
  4836.  #include <linux/linkage.h>
  4837. @@ -124,6 +126,174 @@
  4838.  #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
  4839.  #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
  4840.  #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
  4841. +
  4842. +#ifdef    CONFIG_SMP
  4843. +
  4844. +#define GET_PROCESSOR_ID \
  4845. +    "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \
  4846. +    "movl 32(%edx), %eax\n\t" \
  4847. +    "shrl $24,%eax\n\t" \
  4848. +    "andb $0x0F,%al\n"
  4849. +    
  4850. +#define    ENTER_KERNEL \
  4851. +    "pushl %eax\n\t" \
  4852. +    "pushl %edx\n\t" \
  4853. +    "pushfl\n\t" \
  4854. +    "cli\n\t" \
  4855. +    GET_PROCESSOR_ID \
  4856. +    "1: " \
  4857. +    "lock\n\t" \
  4858. +    "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
  4859. +    "jnc 3f\n\t" \
  4860. +    "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
  4861. +    "je 4f\n\t" \
  4862. +    "2: " \
  4863. +    "incl "SYMBOL_NAME_STR(smp_spins)"\n\t" \
  4864. +    "btl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
  4865. +    "jnc 5f\n\t" \
  4866. +    "lock\n\t" \
  4867. +    "btrl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
  4868. +    "jnc 5f\n\t" \
  4869. +    "movl %cr3,%edx\n\t" \
  4870. +    "movl %edx,%cr3\n" \
  4871. +    "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
  4872. +    "jc 2b\n\t" \
  4873. +    "jmp 1b\n\t" \
  4874. +    "3: " \
  4875. +    "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
  4876. +    "4: " \
  4877. +    "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
  4878. +    "popfl\n\t" \
  4879. +    "popl %edx\n\t" \
  4880. +    "popl %eax\n\t"
  4881. +
  4882. +#define    LEAVE_KERNEL \
  4883. +    "pushfl\n\t" \
  4884. +    "cli\n\t" \
  4885. +    "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
  4886. +    "jnz 1f\n\t" \
  4887. +    "movb $" STR (NO_PROC_ID) ", "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
  4888. +    "lock\n\t" \
  4889. +    "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
  4890. +    "1: " \
  4891. +    "popfl\n\t"
  4892. +    
  4893. +    
  4894. +/*
  4895. + *    the syscall count inc is a gross hack because ret_from_syscall is used by both irq and
  4896. + *    syscall return paths (urghh).
  4897. + */
  4898. +#define BUILD_IRQ(chip,nr,mask) \
  4899. +asmlinkage void IRQ_NAME(nr); \
  4900. +asmlinkage void FAST_IRQ_NAME(nr); \
  4901. +asmlinkage void BAD_IRQ_NAME(nr); \
  4902. +__asm__( \
  4903. +"\n"__ALIGN_STR"\n" \
  4904. +SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
  4905. +    "pushl $-"#nr"-2\n\t" \
  4906. +    SAVE_ALL \
  4907. +    ENTER_KERNEL \
  4908. +    ACK_##chip(mask) \
  4909. +    "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
  4910. +    "sti\n\t" \
  4911. +    "movl %esp,%ebx\n\t" \
  4912. +    "pushl %ebx\n\t" \
  4913. +    "pushl $" #nr "\n\t" \
  4914. +    "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
  4915. +    "addl $8,%esp\n\t" \
  4916. +    "cli\n\t" \
  4917. +    UNBLK_##chip(mask) \
  4918. +    "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
  4919. +    "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
  4920. +    "jmp ret_from_sys_call\n" \
  4921. +"\n"__ALIGN_STR"\n" \
  4922. +SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
  4923. +    SAVE_MOST \
  4924. +    ENTER_KERNEL \
  4925. +    ACK_##chip(mask) \
  4926. +    "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
  4927. +    "pushl $" #nr "\n\t" \
  4928. +    "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
  4929. +    "addl $4,%esp\n\t" \
  4930. +    "cli\n\t" \
  4931. +    UNBLK_##chip(mask) \
  4932. +    "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
  4933. +    LEAVE_KERNEL \
  4934. +    RESTORE_MOST \
  4935. +"\n"__ALIGN_STR"\n" \
  4936. +SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
  4937. +    SAVE_MOST \
  4938. +    ENTER_KERNEL \
  4939. +    ACK_##chip(mask) \
  4940. +    LEAVE_KERNEL \
  4941. +    RESTORE_MOST);
  4942. +    
  4943. +    
  4944. +/*
  4945. + *    Message pass must be a fast IRQ..
  4946. + */
  4947. +
  4948. +#define BUILD_MSGIRQ(chip,nr,mask) \
  4949. +asmlinkage void IRQ_NAME(nr); \
  4950. +asmlinkage void FAST_IRQ_NAME(nr); \
  4951. +asmlinkage void BAD_IRQ_NAME(nr); \
  4952. +__asm__( \
  4953. +"\n"__ALIGN_STR"\n" \
  4954. +SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
  4955. +    "pushl $-"#nr"-2\n\t" \
  4956. +    SAVE_ALL \
  4957. +    ENTER_KERNEL \
  4958. +    ACK_##chip(mask) \
  4959. +    "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
  4960. +    "sti\n\t" \
  4961. +    "movl %esp,%ebx\n\t" \
  4962. +    "pushl %ebx\n\t" \
  4963. +    "pushl $" #nr "\n\t" \
  4964. +    "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
  4965. +    "addl $8,%esp\n\t" \
  4966. +    "cli\n\t" \
  4967. +    UNBLK_##chip(mask) \
  4968. +    "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
  4969. +    "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
  4970. +    "jmp ret_from_sys_call\n" \
  4971. +"\n"__ALIGN_STR"\n" \
  4972. +SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
  4973. +    SAVE_MOST \
  4974. +    ACK_##chip(mask) \
  4975. +    "incl "SYMBOL_NAME_STR(ipi_count)"\n\t" \
  4976. +    "pushl $" #nr "\n\t" \
  4977. +    "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
  4978. +    "addl $4,%esp\n\t" \
  4979. +    "cli\n\t" \
  4980. +    UNBLK_##chip(mask) \
  4981. +    RESTORE_MOST \
  4982. +"\n"__ALIGN_STR"\n" \
  4983. +SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
  4984. +    SAVE_MOST \
  4985. +    ACK_##chip(mask) \
  4986. +    RESTORE_MOST);
  4987. +
  4988. +#define BUILD_RESCHEDIRQ(nr) \
  4989. +asmlinkage void IRQ_NAME(nr); \
  4990. +__asm__( \
  4991. +"\n"__ALIGN_STR"\n" \
  4992. +SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
  4993. +    "pushl $-"#nr"-2\n\t" \
  4994. +    SAVE_ALL \
  4995. +    ENTER_KERNEL \
  4996. +    "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
  4997. +    "sti\n\t" \
  4998. +    "movl %esp,%ebx\n\t" \
  4999. +    "pushl %ebx\n\t" \
  5000. +    "pushl $" #nr "\n\t" \
  5001. +    "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \
  5002. +    "addl $8,%esp\n\t" \
  5003. +    "cli\n\t" \
  5004. +    "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
  5005. +    "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
  5006. +    "jmp ret_from_sys_call\n");
  5007. +#else
  5008.      
  5009.  #define BUILD_IRQ(chip,nr,mask) \
  5010.  asmlinkage void IRQ_NAME(nr); \
  5011. @@ -164,4 +334,5 @@
  5012.      ACK_##chip(mask) \
  5013.      RESTORE_MOST);
  5014.  
  5015. +#endif
  5016.  #endif
  5017. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/locks.h linux/include/asm-i386/locks.h
  5018. --- v1.3.30/linux/include/asm-i386/locks.h    Thu Jan  1 02:00:00 1970
  5019. +++ linux/include/asm-i386/locks.h    Mon Oct  2 14:25:11 1995
  5020. @@ -0,0 +1,133 @@
  5021. +/*
  5022. + *    SMP locks primitives for building ix86 locks
  5023. + *    (not yet used).
  5024. + *
  5025. + *        Alan Cox, alan@cymru.net, 1995
  5026. + */
  5027. +/*
  5028. + *    This would be much easier but far less clear and easy
  5029. + *    to borrow for other processors if it was just assembler.
  5030. + */
  5031. +
  5032. +extern __inline__ void prim_spin_lock(struct spinlock *sp)
  5033. +{
  5034. +    int processor=smp_processor_id();
  5035. +    
  5036. +    /*
  5037. +     *    Grab the lock bit
  5038. +     */
  5039. +     
  5040. +    while(lock_set_bit(0,&sp->lock))
  5041. +    {
  5042. +        /*
  5043. +         *    Failed, but thats cos we own it!
  5044. +         */
  5045. +         
  5046. +        if(sp->cpu==processor)
  5047. +        {
  5048. +            sp->users++;
  5049. +            return 0;
  5050. +        }
  5051. +        /*
  5052. +         *    Spin in the cache S state if possible
  5053. +         */
  5054. +        while(sp->lock)
  5055. +        {
  5056. +            /*
  5057. +             *    Wait for any invalidates to go off
  5058. +             */
  5059. +             
  5060. +            if(smp_invalidate_needed&(1<<processor));
  5061. +                while(lock_clear_bit(processor,&smp_invalidate_needed))
  5062. +                    local_invalidate();
  5063. +            sp->spins++;
  5064. +        }
  5065. +        /*
  5066. +         *    Someone wrote the line, we go 'I' and get
  5067. +         *    the cache entry. Now try and regrab
  5068. +         */
  5069. +    }
  5070. +    sp->users++;sp->cpu=processor;
  5071. +    return 1;
  5072. +}
  5073. +
  5074. +/*
  5075. + *    Release a spin lock
  5076. + */
  5077. +extern __inline__ int prim_spin_unlock(struct spinlock *sp)
  5078. +{
  5079. +    /* This is safe. The decrement is still guarded by the lock. A multilock would
  5080. +       not be safe this way */
  5081. +    if(!--sp->users)
  5082. +    {
  5083. +        lock_clear_bit(0,&sp->lock);sp->cpu= NO_PROC_ID;
  5084. +        return 1;
  5085. +    }
  5086. +    return 0;
  5087. +}
  5088. +
  5089. +
  5090. +/*
  5091. + *    Non blocking lock grab
  5092. + */
  5093. +extern __inline__ int prim_spin_lock_nb(struct spinlock *sp)
  5094. +{
  5095. +    if(lock_set_bit(0,&sp->lock))
  5096. +        return 0;        /* Locked already */
  5097. +    sp->users++;
  5098. +    return 1;            /* We got the lock */
  5099. +}
  5100. +
  5101. +
  5102. +/*
  5103. + *    These wrap the locking primtives up for usage
  5104. + */
  5105. +extern __inline__ void spinlock(struct spinlock *sp)
  5106. +{
  5107. +    if(sp->priority<current->lock_order)
  5108. +        panic("lock order violation: %s (%d)\n", sp->name, current->lock_order);
  5109. +    if(prim_spin_lock(sp))
  5110. +    {
  5111. +        /*
  5112. +         *    We got a new lock. Update the priority chain
  5113. +         */
  5114. +        sp->oldpri=current->lock_order;
  5115. +        current->lock_order=sp->priority;
  5116. +    }
  5117. +}
  5118. +
  5119. +extern __inline__ void spinunlock(struct spinlock *sp)
  5120. +{
  5121. +    if(current->lock_order!=sp->priority)
  5122. +        panic("lock release order violation %s (%d)\n", sp->name, current->lock_order);
  5123. +    if(prim_spin_unlock(sp))
  5124. +    {
  5125. +        /*
  5126. +         *    Update the debugging lock priority chain. We dumped
  5127. +         *    our last right to the lock.
  5128. +         */
  5129. +        current->lock_order=sp->oldpri;
  5130. +    }    
  5131. +}
  5132. +
  5133. +extern __inline__ void spintestlock(struct spinlock *sp)
  5134. +{
  5135. +    /*
  5136. +     *    We do no sanity checks, its legal to optimistically
  5137. +     *    get a lower lock.
  5138. +     */
  5139. +    prim_spin_lock_nb(sp);
  5140. +}
  5141. +
  5142. +extern __inline__ void spintestunlock(struct spinlock *sp)
  5143. +{
  5144. +    /*
  5145. +     *    A testlock doesnt update the lock chain so we
  5146. +     *    must not update it on free
  5147. +     */
  5148. +    prim_spin_unlock(sp);
  5149. +}
  5150. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
  5151. --- v1.3.30/linux/include/asm-i386/page.h    Mon Sep 25 12:26:23 1995
  5152. +++ linux/include/asm-i386/page.h    Mon Oct  2 14:25:11 1995
  5153. @@ -60,6 +60,8 @@
  5154.   *
  5155.   * ..but the i386 has somewhat limited invalidation capabilities.
  5156.   */
  5157. +#ifndef CONFIG_SMP
  5158.  #define invalidate() \
  5159.  __asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
  5160.  
  5161. @@ -68,6 +70,14 @@
  5162.  do { if ((task)->mm == current->mm) invalidate(); } while (0)
  5163.  #define invalidate_page(task,addr) \
  5164.  do { if ((task)->mm == current->mm) invalidate(); } while (0)
  5165. +
  5166. +#else
  5167. +#include <asm/smp.h>
  5168. +#define local_invalidate() \
  5169. +__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
  5170. +#define invalidate() \
  5171. +    smp_invalidate();
  5172. +#endif
  5173.  
  5174.  /* Certain architectures need to do special things when pte's
  5175.   * within a page table are directly modified.  Thus, the following
  5176. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
  5177. --- v1.3.30/linux/include/asm-i386/smp.h    Wed Sep 27 16:00:00 1995
  5178. +++ linux/include/asm-i386/smp.h    Mon Oct  2 14:25:11 1995
  5179. @@ -1,6 +1,7 @@
  5180.  #ifndef __ASM_SMP_H
  5181.  #define __ASM_SMP_H
  5182.  
  5183. +#ifdef CONFIG_SMP
  5184.  #ifndef ASSEMBLY
  5185.  
  5186.  #include <asm/i82489.h>
  5187. @@ -165,7 +166,7 @@
  5188.  };
  5189.  
  5190.  
  5191. -extern struct cpuinfo_x86 cpu_data[NR_PROCS];
  5192. +extern struct cpuinfo_x86 cpu_data[NR_CPUS];
  5193.  
  5194.  /*
  5195.   *    Private routines/data
  5196. @@ -174,7 +175,7 @@
  5197.  extern void smp_scan_config(unsigned long, unsigned long);
  5198.  extern unsigned long smp_alloc_memory(unsigned long mem_base);
  5199.  extern unsigned char *apic_reg;
  5200. -extern unsigned char *kernel_stacks[NR_PROCS];
  5201. +extern unsigned char *kernel_stacks[NR_CPUS];
  5202.  extern unsigned char boot_cpu_id;
  5203.  extern unsigned long cpu_present_map;
  5204.  extern void smp_invalidate(void);
  5205. @@ -227,5 +228,5 @@
  5206.  #endif /* !ASSEMBLY */
  5207.  
  5208.  #define NO_PROC_ID        0xFF        /* No processor magic marker */
  5209. -
  5210. +#endif
  5211.  #endif
  5212. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
  5213. --- v1.3.30/linux/include/asm-i386/system.h    Tue Jul 18 16:28:58 1995
  5214. +++ linux/include/asm-i386/system.h    Mon Oct  2 14:25:11 1995
  5215. @@ -47,9 +47,62 @@
  5216.   *
  5217.   * It also reloads the debug regs if necessary..
  5218.   */
  5219. +
  5220. +#ifdef CONFIG_SMP
  5221. +    /*
  5222. +     *    Keep the lock depth straight. If we switch on an interrupt from
  5223. +     *    kernel->user task we need to lose a depth, and if we switch the
  5224. +     *    other way we need to gain a depth. Same layer switches come out
  5225. +     *    the same.
  5226. +     *
  5227. +     *    We spot a switch in user mode because the kernel counter is the
  5228. +     *    same as the interrupt counter depth. (We never switch during the
  5229. +     *    message/invalidate IPI).
  5230. +     *
  5231. +     *    We fsave/fwait so that an exception goes off at the right time
  5232. +     *    (as a call from the fsave or fwait in effect) rather than to
  5233. +     *    the wrong process.
  5234. +     */
  5235. +
  5236. +#define switch_to(tsk) do { \
  5237. +    cli();\
  5238. +    if(current->flags&PF_USEDFPU) \
  5239. +    { \
  5240. +        __asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard)); \
  5241. +        __asm__ __volatile__("fwait"); \
  5242. +        current->flags&=~PF_USEDFPU;     \
  5243. +    } \
  5244. +    current->lock_depth=syscall_count; \
  5245. +    kernel_counter+=next->lock_depth-current->lock_depth; \
  5246. +    syscall_count=next->lock_depth; \
  5247. +__asm__("pushl %%edx\n\t" \
  5248. +    "movl "SYMBOL_NAME_STR(apic_reg)",%%edx\n\t" \
  5249. +    "movl 0x20(%%edx), %%edx\n\t" \
  5250. +    "shrl $22,%%edx\n\t" \
  5251. +    "and  $0x3C,%%edx\n\t" \
  5252. +    "xchgl %%ecx,"SYMBOL_NAME_STR(current_set)"(,%%edx)\n\t" \
  5253. +    "popl %%edx\n\t" \
  5254. +    "ljmp %0\n\t" \
  5255. +    "sti\n\t" \
  5256. +    : /* no output */ \
  5257. +    :"m" (*(((char *)&tsk->tss.tr)-4)), \
  5258. +     "c" (tsk) \
  5259. +    :"cx"); \
  5260. +    /* Now maybe reload the debug registers */ \
  5261. +    if(current->debugreg[7]){ \
  5262. +        loaddebug(0); \
  5263. +        loaddebug(1); \
  5264. +        loaddebug(2); \
  5265. +        loaddebug(3); \
  5266. +        loaddebug(6); \
  5267. +    } \
  5268. +} while (0)
  5269. +
  5270. +#else
  5271.  #define switch_to(tsk) do { \
  5272.  __asm__("cli\n\t" \
  5273. -    "xchgl %%ecx,"SYMBOL_NAME_STR(current)"\n\t" \
  5274. +    "xchgl %%ecx,"SYMBOL_NAME_STR(current_set)"\n\t" \
  5275.      "ljmp %0\n\t" \
  5276.      "sti\n\t" \
  5277.      "cmpl %%ecx,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \
  5278. @@ -69,6 +122,7 @@
  5279.          loaddebug(6); \
  5280.      } \
  5281.  } while (0)
  5282. +#endif
  5283.  
  5284.  #define _set_base(addr,base) \
  5285.  __asm__("movw %%dx,%0\n\t" \
  5286. diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
  5287. --- v1.3.30/linux/include/asm-i386/unistd.h    Wed Sep 13 12:45:32 1995
  5288. +++ linux/include/asm-i386/unistd.h    Sat Sep 30 18:03:16 1995
  5289. @@ -150,6 +150,8 @@
  5290.  #define __NR__newselect        142
  5291.  #define __NR_flock        143
  5292.  #define __NR_msync        144
  5293. +#define __NR_readv        145
  5294. +#define __NR_writev        146
  5295.  
  5296.  /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
  5297.  #define _syscall0(type,name) \
  5298. diff -u --recursive --new-file v1.3.30/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
  5299. --- v1.3.30/linux/include/linux/cdrom.h    Fri Sep 15 11:13:02 1995
  5300. +++ linux/include/linux/cdrom.h    Sun Oct  1 19:51:44 1995
  5301. @@ -65,6 +65,13 @@
  5302.   * CDROM IOCTL structures
  5303.   */
  5304.  
  5305. +struct cdrom_blk 
  5306. +{
  5307. +    unsigned from;
  5308. +    unsigned short len;
  5309. +};
  5310. +
  5311. +
  5312.  struct cdrom_msf 
  5313.  {
  5314.      u_char    cdmsf_min0;    /* start minute */
  5315. @@ -285,7 +292,10 @@
  5316.  #define CDROMREADCOOKED        0x5315    /* read data in cooked mode */
  5317.  #define CDROMSEEK        0x5316  /*seek msf address*/
  5318.    
  5319. -
  5320. +/*
  5321. + * for playing audio in logical block addressing mode
  5322. + */
  5323. +#define CDROMPLAYBLK        0x5317    /* (struct cdrom_blk) */
  5324.  
  5325.  /*
  5326.   * CD-ROM-specific SCSI command opcodes
  5327. diff -u --recursive --new-file v1.3.30/linux/include/linux/igmp.h linux/include/linux/igmp.h
  5328. --- v1.3.30/linux/include/linux/igmp.h    Wed Sep 13 12:45:32 1995
  5329. +++ linux/include/linux/igmp.h    Mon Oct  2 14:25:11 1995
  5330. @@ -42,6 +42,7 @@
  5331.  #define IGMP_MTRACE_RESP        0x1e
  5332.  #define IGMP_MTRACE            0x1f
  5333.  
  5334. +
  5335.  /*
  5336.   *    Use the BSD names for these for compatibility
  5337.   */
  5338. diff -u --recursive --new-file v1.3.30/linux/include/linux/mroute.h linux/include/linux/mroute.h
  5339. --- v1.3.30/linux/include/linux/mroute.h    Wed Sep 13 12:45:32 1995
  5340. +++ linux/include/linux/mroute.h    Mon Oct  2 14:25:11 1995
  5341. @@ -1,5 +1,6 @@
  5342.  #ifndef __LINUX_MROUTE_H
  5343.  #define __LINUX_MROUTE_H
  5344. +
  5345.  /*
  5346.   *    Based on the MROUTING 3.5 defines primarily to keep
  5347.   *    source compatibility with BSD.
  5348. @@ -117,19 +118,53 @@
  5349.  extern int ip_mroute_getsockopt(struct sock *, int, char *, int *);
  5350.  extern int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg);
  5351.  extern void mroute_close(struct sock *sk);
  5352. +extern void ipmr_forward(struct sk_buff *skb, int is_frag);
  5353.  
  5354.  
  5355.  struct vif_device
  5356.  {
  5357. -    struct device *dev;        /* Device we are using */
  5358. -    struct route *rt_cache;        /* Tunnel route cache */
  5359. -    unsigned long bytes_in,bytes_out;
  5360. -    unsigned long pkt_in,pkt_out;    /* Statistics */
  5361. -    unsigned long rate_limit;    /* Traffic shaping (NI) */
  5362. -    unsigned char threshold;    /* TTL threshold */
  5363. -    unsigned short flags;        /* Control flags */
  5364. -    unsigned long local,remote;    /* Addresses (remote for tunnels) */
  5365. +    struct device     *dev;            /* Device we are using */
  5366. +    struct route     *rt_cache;        /* Tunnel route cache */
  5367. +    unsigned long    bytes_in,bytes_out;
  5368. +    unsigned long    pkt_in,pkt_out;        /* Statistics             */
  5369. +    unsigned long    rate_limit;        /* Traffic shaping (NI)     */
  5370. +    unsigned char    threshold;        /* TTL threshold         */
  5371. +    unsigned short    flags;            /* Control flags         */
  5372. +    unsigned long    local,remote;        /* Addresses(remote for tunnels)*/
  5373.  };
  5374.  
  5375. +struct mfc_cache 
  5376. +{
  5377. +    struct mfc_cache *next;            /* Next entry on cache line     */
  5378. +    __u32 mfc_mcastgrp;            /* Group the entry belongs to     */
  5379. +    __u32 mfc_origin;            /* Source of packet         */
  5380. +    vifi_t mfc_parent;            /* Source interface        */
  5381. +    struct timer_list mfc_timer;        /* Expiry timer            */
  5382. +    int mfc_flags;                /* Flags on line        */
  5383. +    struct sk_buff_head mfc_unresolved;    /* Unresolved buffers        */
  5384. +    int mfc_queuelen;            /* Unresolved buffer counter    */
  5385. +    unsigned char mfc_ttls[MAXVIFS];    /* TTL thresholds        */
  5386. +};
  5387. +
  5388. +#define MFC_QUEUED        1
  5389. +#define MFC_RESOLVED        2
  5390. +
  5391. +
  5392. +#define MFC_LINES        64
  5393. +
  5394. +#ifdef __BIG_ENDIAN
  5395. +#define MFC_HASH(a,b)    ((((a)>>24)^((b)>>26))&(MFC_LINES-1))
  5396. +#else
  5397. +#define MFC_HASH(a,b)    (((a)^((b)>>2))&(MFC_LINES-1))
  5398. +#endif        
  5399. +
  5400.  #endif
  5401. +
  5402. +/*
  5403. + *    Pseudo messages used by mrouted
  5404. + */
  5405. +
  5406. +#define IGMPMSG_NOCACHE        1        /* Kernel cache fill request to mrouted */
  5407. +#define IGMPMSG_WRONGVIF    2        /* For PIM assert processing (unused) */
  5408. +
  5409.  #endif
  5410. diff -u --recursive --new-file v1.3.30/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
  5411. --- v1.3.30/linux/include/linux/proc_fs.h    Mon Sep 25 12:26:23 1995
  5412. +++ linux/include/linux/proc_fs.h    Wed Oct  4 08:21:33 1995
  5413. @@ -67,6 +67,8 @@
  5414.      PROC_NET_SNMP,
  5415.      PROC_NET_RARP,
  5416.      PROC_NET_IGMP,
  5417. +    PROC_NET_IPMR_VIF,
  5418. +    PROC_NET_IPMR_MFC,
  5419.      PROC_NET_IPFWFWD,
  5420.      PROC_NET_IPFWBLK,
  5421.      PROC_NET_IPACCT,
  5422. diff -u --recursive --new-file v1.3.30/linux/include/linux/sched.h linux/include/linux/sched.h
  5423. --- v1.3.30/linux/include/linux/sched.h    Wed Sep 27 16:00:00 1995
  5424. +++ linux/include/linux/sched.h    Wed Oct  4 08:20:52 1995
  5425. @@ -1,6 +1,8 @@
  5426.  #ifndef _LINUX_SCHED_H
  5427.  #define _LINUX_SCHED_H
  5428.  
  5429. +#include <linux/config.h>
  5430. +
  5431.  /*
  5432.   * define DEBUG if you want the wait-queues to have some extra
  5433.   * debugging code. It's not normally used, but might catch some
  5434. @@ -21,6 +23,8 @@
  5435.  #include <asm/system.h>
  5436.  #include <asm/page.h>
  5437.  
  5438. +#include <linux/smp.h>
  5439. +
  5440.  /*
  5441.   * cloning flags:
  5442.   */
  5443. @@ -215,6 +219,10 @@
  5444.      struct mm_struct *mm;
  5445.  /* signal handlers */
  5446.      struct signal_struct *sig;
  5447. +#ifdef CONFIG_SMP
  5448. +    int processor;
  5449. +    int lock_depth;        /* Lock depth. We can context swithc in and out of holding a syscall kernel lock... */    
  5450. +#endif    
  5451.  };
  5452.  
  5453.  /*
  5454. @@ -228,6 +236,8 @@
  5455.  #define PF_STARTING    0x00000100    /* being created */
  5456.  #define PF_EXITING    0x00000200    /* getting shut down */
  5457.  
  5458. +#define PF_USEDFPU    0x00100000    /* Process used the FPU this quantum (SMP only) */
  5459. +
  5460.  /*
  5461.   * Limit the stack by to some sane default: root can always
  5462.   * increase this limit if needed..  8MB seems reasonable.
  5463. @@ -275,7 +285,12 @@
  5464.  extern struct task_struct init_task;
  5465.  extern struct task_struct *task[NR_TASKS];
  5466.  extern struct task_struct *last_task_used_math;
  5467. -extern struct task_struct *current;
  5468. +extern struct task_struct *current_set[NR_CPUS];
  5469. +/*
  5470. + *    On a single processor system this comes out as current_set[0] when cpp
  5471. + *    has finished with it, which gcc will optimise away.
  5472. + */
  5473. +#define current (current_set[smp_processor_id()])    /* Current on this processor */
  5474.  extern unsigned long volatile jiffies;
  5475.  extern unsigned long itimer_ticks;
  5476.  extern unsigned long itimer_next;
  5477. diff -u --recursive --new-file v1.3.30/linux/include/linux/smp.h linux/include/linux/smp.h
  5478. --- v1.3.30/linux/include/linux/smp.h    Wed Sep 13 12:45:33 1995
  5479. +++ linux/include/linux/smp.h    Mon Oct  2 14:25:11 1995
  5480. @@ -6,6 +6,7 @@
  5481.   *        Alan Cox. <alan@cymru.net>
  5482.   */
  5483.  
  5484. +#ifdef CONFIG_SMP
  5485.  #include <asm/smp.h>
  5486.  
  5487.   
  5488. @@ -28,4 +29,15 @@
  5489.  #define MSG_STOP_CPU        0x0002        /* Sent to shut down slave CPU's when rebooting */
  5490.  #define MSG_RESCHEDULE        0x0003        /* Reschedule request from master CPU */
  5491.  
  5492. +#else
  5493. +
  5494. +/*
  5495. + *    These macros fold the SMP functionality into a single CPU system
  5496. + */
  5497. +#define smp_num_cpus            1
  5498. +#define smp_processor_id()        0
  5499. +#define smp_message_pass(t,m,d,w)    
  5500. +#define smp_threads_ready        1
  5501. +#endif
  5502.  #endif
  5503. diff -u --recursive --new-file v1.3.30/linux/include/linux/tasks.h linux/include/linux/tasks.h
  5504. --- v1.3.30/linux/include/linux/tasks.h    Wed Sep 13 12:45:33 1995
  5505. +++ linux/include/linux/tasks.h    Mon Oct  2 14:25:11 1995
  5506. @@ -5,7 +5,11 @@
  5507.   * This is the maximum nr of tasks - change it if you need to
  5508.   */
  5509.   
  5510. -#define NR_PROCS    32        /* Max processors that can be running */
  5511. +#ifdef CONFIG_SMP
  5512. +#define NR_CPUS    32        /* Max processors that can be running in SMP */
  5513. +#else
  5514. +#define NR_CPUS 1
  5515. +#endif
  5516.  
  5517.  #define NR_TASKS    512
  5518.  
  5519. diff -u --recursive --new-file v1.3.30/linux/include/net/netlink.h linux/include/net/netlink.h
  5520. --- v1.3.30/linux/include/net/netlink.h    Thu Jan  1 02:00:00 1970
  5521. +++ linux/include/net/netlink.h    Mon Oct  2 14:25:11 1995
  5522. @@ -0,0 +1,13 @@
  5523. +#define NET_MAJOR 18        /* Major 18 is reserved for networking         */
  5524. +#define MAX_LINKS 3        /* 18,0 for route updates, 18,1 for SKIP     */
  5525. +#define MAX_QBYTES 32768    /* Maximum bytes in the queue             */
  5526. +
  5527. +extern int netlink_attach(int unit, int (*function)(struct sk_buff *skb));
  5528. +extern void netlink_detach(int unit);
  5529. +extern int netlink_post(int unit, struct sk_buff *skb);
  5530. +extern void init_netlink(void);
  5531. +
  5532. +#define NETLINK_ROUTE        0    /* Routing/device hook                */
  5533. +#define NETLINK_SKIP        1    /* Reserved for ENskip              */
  5534. +#define NETLINK_USERSOCK    2    /* Reserved for user mode socket protocols     */
  5535. +
  5536. diff -u --recursive --new-file v1.3.30/linux/init/main.c linux/init/main.c
  5537. --- v1.3.30/linux/init/main.c    Wed Sep 27 16:00:00 1995
  5538. +++ linux/init/main.c    Mon Oct  2 14:25:11 1995
  5539. @@ -293,11 +293,14 @@
  5540.     better than 1% */
  5541.  #define LPS_PREC 8
  5542.  
  5543. -static void calibrate_delay(void)
  5544. +void calibrate_delay(void)
  5545.  {
  5546.      int ticks;
  5547.      int loopbit;
  5548.      int lps_precision = LPS_PREC;
  5549. +#ifdef CONFIG_SMP
  5550. +    loops_per_sec = (1<<12);
  5551. +#endif        
  5552.  
  5553.      printk("Calibrating delay loop.. ");
  5554.      while (loops_per_sec <<= 1) {
  5555. @@ -418,9 +421,76 @@
  5556.  
  5557.  static char init_stack[PAGE_SIZE];
  5558.  
  5559. +#ifdef CONFIG_SMP
  5560. +/*
  5561. + *    Activate a secondary processor.
  5562. + */
  5563. +asmlinkage void start_secondary(void)
  5564. +{
  5565. +    trap_init();
  5566. +    init_IRQ();
  5567. +    smp_callin();
  5568. +    for(;;)
  5569. +        idle();
  5570. +}
  5571. +
  5572. +/*
  5573. + *    Called by CPU#0 to activate the rest.
  5574. + */
  5575. +static void smp_init(void)
  5576. +{
  5577. +    int i=0;
  5578. +    smp_boot_cpus();
  5579. +    
  5580. +    /*
  5581. +     *    Create the slave init tasks. At this point
  5582. +     *    fork will create them all ask task 0
  5583. +     */
  5584. +
  5585. +    for(i=1;i<smp_num_cpus;i++)
  5586. +    {
  5587. +        fork();
  5588. +        /* We are forking multiple process 0's. This makes it harder
  5589. +           to tell them apart than we would like ;) */
  5590. +        if(current!=task[0])
  5591. +        {
  5592. +            for(;;)
  5593. +                idle();
  5594. +        }
  5595. +        /*
  5596. +         *    Assume linear processor numbering
  5597. +         */
  5598. +        current_set[i]=task[i];
  5599. +        current_set[i]->processor=i;
  5600. +    }
  5601. +    smp_threads_ready=1;
  5602. +    smp_commence();
  5603. +}        
  5604. +    
  5605. +#endif
  5606. +
  5607. +/*
  5608. + *    Activate the first processor.
  5609. + */
  5610.  asmlinkage void start_kernel(void)
  5611.  {
  5612.      char * command_line;
  5613. +
  5614. +/*
  5615. + *    This little check will move.
  5616. + */
  5617. +
  5618. +#ifdef CONFIG_SMP    
  5619. +    static int first_cpu=1;
  5620. +    
  5621. +    if(!first_cpu)
  5622. +        start_secondary();
  5623. +    first_cpu=0;
  5624. +    
  5625. +#endif    
  5626.  /*
  5627.   * Interrupts are still disabled. Do necessary setups, then
  5628.   * enable them
  5629. @@ -477,7 +547,9 @@
  5630.      check_bugs();
  5631.  
  5632.      printk(linux_banner);
  5633. -
  5634. +#ifdef CONFIG_SMP    
  5635. +    smp_init();
  5636. +#endif
  5637.      /* we count on the clone going ok */
  5638.      if (!clone(CLONE_VM, init_stack+sizeof(init_stack)))
  5639.          init();
  5640. diff -u --recursive --new-file v1.3.30/linux/kernel/exit.c linux/kernel/exit.c
  5641. --- v1.3.30/linux/kernel/exit.c    Mon Sep 18 14:54:10 1995
  5642. +++ linux/kernel/exit.c    Mon Oct  2 14:25:11 1995
  5643. @@ -6,6 +6,7 @@
  5644.  
  5645.  #undef DEBUG_PROC_TREE
  5646.  
  5647. +#include <linux/config.h>
  5648.  #include <linux/wait.h>
  5649.  #include <linux/errno.h>
  5650.  #include <linux/signal.h>
  5651. @@ -72,7 +73,7 @@
  5652.  
  5653.  void notify_parent(struct task_struct * tsk)
  5654.  {
  5655. -    if (tsk->p_pptr == task[1])
  5656. +    if (tsk->p_pptr == task[smp_num_cpus])        /* Init */
  5657.          tsk->exit_signal = SIGCHLD;
  5658.      send_sig(tsk->exit_signal, tsk->p_pptr, 1);
  5659.      wake_up_interruptible(&tsk->p_pptr->wait_chldexit);
  5660. @@ -349,8 +350,8 @@
  5661.  
  5662.      for_each_task(p) {
  5663.          if (p->p_opptr == father)
  5664. -            if (task[1])
  5665. -                p->p_opptr = task[1];
  5666. +            if (task[smp_num_cpus])    /* init */
  5667. +                p->p_opptr = task[smp_num_cpus];
  5668.              else
  5669.                  p->p_opptr = task[0];
  5670.      }
  5671. @@ -457,8 +458,8 @@
  5672.          current->p_cptr = p->p_osptr;
  5673.          p->p_ysptr = NULL;
  5674.          p->flags &= ~(PF_PTRACED|PF_TRACESYS);
  5675. -        if (task[1] && task[1] != current)
  5676. -            p->p_pptr = task[1];
  5677. +        if (task[smp_num_cpus] && task[smp_num_cpus] != current) /* init */
  5678. +            p->p_pptr = task[smp_num_cpus];
  5679.          else
  5680.              p->p_pptr = task[0];
  5681.          p->p_osptr = p->p_pptr->p_cptr;
  5682. diff -u --recursive --new-file v1.3.30/linux/kernel/fork.c linux/kernel/fork.c
  5683. --- v1.3.30/linux/kernel/fork.c    Wed Sep 27 16:00:00 1995
  5684. +++ linux/kernel/fork.c    Tue Oct  3 12:47:42 1995
  5685. @@ -11,6 +11,7 @@
  5686.   * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
  5687.   */
  5688.  
  5689. +#include <linux/config.h>
  5690.  #include <linux/errno.h>
  5691.  #include <linux/sched.h>
  5692.  #include <linux/kernel.h>
  5693. @@ -20,6 +21,7 @@
  5694.  #include <linux/ptrace.h>
  5695.  #include <linux/malloc.h>
  5696.  #include <linux/ldt.h>
  5697. +#include <linux/smp.h>
  5698.  
  5699.  #include <asm/segment.h>
  5700.  #include <asm/system.h>
  5701. @@ -40,15 +42,17 @@
  5702.              return -EAGAIN;
  5703.      }
  5704.  repeat:
  5705. -    if ((++last_pid) & 0xffff8000)
  5706. -        last_pid=1;
  5707. +    if(smp_threads_ready) {
  5708. +        if ((++last_pid) & 0xffff8000)
  5709. +            last_pid=1;
  5710. +    }
  5711.      this_user_tasks = 0;
  5712.      for_each_task (p) {
  5713.          if (p->uid == current->uid)
  5714.              this_user_tasks++;
  5715. -        if (p->pid == last_pid ||
  5716. +        if (smp_threads_ready && (p->pid == last_pid ||
  5717.              p->pgrp == last_pid ||
  5718. -            p->session == last_pid)
  5719. +            p->session == last_pid))
  5720.              goto repeat;
  5721.      }
  5722.      if (this_user_tasks > current->rlim[RLIMIT_NPROC].rlim_cur)
  5723. @@ -224,6 +228,10 @@
  5724.      p->tty_old_pgrp = 0;
  5725.      p->utime = p->stime = 0;
  5726.      p->cutime = p->cstime = 0;
  5727. +#ifdef CONFIG_SMP
  5728. +    p->processor = NO_PROC_ID;
  5729. +    p->lock_depth = 1;
  5730. +#endif
  5731.      p->start_time = jiffies;
  5732.      task[nr] = p;
  5733.      SET_LINKS(p);
  5734. diff -u --recursive --new-file v1.3.30/linux/kernel/ksyms.c linux/kernel/ksyms.c
  5735. --- v1.3.30/linux/kernel/ksyms.c    Wed Sep 27 16:00:00 1995
  5736. +++ linux/kernel/ksyms.c    Mon Oct  2 14:25:12 1995
  5737. @@ -273,7 +273,10 @@
  5738.      X(sleep_on),
  5739.      X(interruptible_sleep_on),
  5740.      X(schedule),
  5741. -    X(current),
  5742. +    X(current_set),
  5743. +#if defined(__i386__) && defined(CONFIG_SMP)
  5744. +    X(apic_reg),        /* Needed internally for the I386 inlines */
  5745. +#endif    
  5746.      X(jiffies),
  5747.      X(xtime),
  5748.      X(loops_per_sec),
  5749. diff -u --recursive --new-file v1.3.30/linux/kernel/sched.c linux/kernel/sched.c
  5750. --- v1.3.30/linux/kernel/sched.c    Wed Sep 27 16:00:00 1995
  5751. +++ linux/kernel/sched.c    Tue Oct  3 12:48:39 1995
  5752. @@ -26,6 +26,7 @@
  5753.  #include <linux/tqueue.h>
  5754.  #include <linux/resource.h>
  5755.  #include <linux/mm.h>
  5756. +#include <linux/smp.h>
  5757.  
  5758.  #include <asm/system.h>
  5759.  #include <asm/io.h>
  5760. @@ -88,7 +89,7 @@
  5761.  
  5762.  unsigned long volatile jiffies=0;
  5763.  
  5764. -struct task_struct *current = &init_task;
  5765. +struct task_struct *current_set[NR_CPUS];
  5766.  struct task_struct *last_task_used_math = NULL;
  5767.  
  5768.  struct task_struct * task[NR_TASKS] = {&init_task, };
  5769. @@ -181,6 +182,12 @@
  5770.      struct task_struct * p;
  5771.      struct task_struct * next;
  5772.      unsigned long timeout = 0;
  5773. +    
  5774. +#ifdef CONFIG_SMP_DEBUG
  5775. +    int proc=smp_processor_id();
  5776. +    if(active_kernel_processor!=proc)
  5777. +        panic("active kernel processor set wrongly! %d not %d\n", active_kernel_processor,proc);
  5778. +#endif
  5779.  
  5780.  /* check alarm, wake up any interruptible tasks that have got a signal */
  5781.  
  5782. @@ -210,6 +217,13 @@
  5783.      }
  5784.      p = init_task.next_run;
  5785.      sti();
  5786. +    
  5787. +#ifdef CONFIG_SMP
  5788. +    /*
  5789. +     *    This is safe as we do not permit re-entry of schedule()
  5790. +     */
  5791. +    current->processor = NO_PROC_ID;    
  5792. +#endif    
  5793.  
  5794.  /*
  5795.   * Note! there may appear new tasks on the run-queue during this, as
  5796. @@ -220,6 +234,13 @@
  5797.      c = -1000;
  5798.      next = &init_task;
  5799.      while (p != &init_task) {
  5800. +#ifdef CONFIG_SMP    
  5801. +        /* We are not permitted to run a task someone else is running */
  5802. +        if (p->processor != NO_PROC_ID) {
  5803. +            p = p->next_run;
  5804. +            continue;
  5805. +        }
  5806. +#endif        
  5807.          if (p->counter > c)
  5808.              c = p->counter, next = p;
  5809.          p = p->next_run;
  5810. @@ -230,6 +251,20 @@
  5811.          for_each_task(p)
  5812.              p->counter = (p->counter >> 1) + p->priority;
  5813.      }
  5814. +#ifdef CONFIG_SMP    
  5815. +    
  5816. +    /*
  5817. +     *    Context switching between two idle threads is pointless.
  5818. +     */
  5819. +    if(!current->pid && !next->pid)
  5820. +        next=current;
  5821. +    /*
  5822. +     *    Allocate process to CPU
  5823. +     */
  5824. +     
  5825. +     next->processor = smp_processor_id();
  5826. +     
  5827. +#endif     
  5828.      if (current != next) {
  5829.          struct timer_list timer;
  5830.  
  5831. @@ -446,6 +481,9 @@
  5832.                 (*p)->state == TASK_UNINTERRUPTIBLE ||
  5833.                 (*p)->state == TASK_SWAPPING))
  5834.              nr += FIXED_1;
  5835. +#ifdef CONFIG_SMP
  5836. +    nr-=(smp_num_cpus-1)*FIXED_1;
  5837. +#endif            
  5838.      return nr;
  5839.  }
  5840.  
  5841. @@ -651,8 +689,7 @@
  5842.      } else
  5843.          xtime.tv_usec += tick + time_adjust_step;
  5844.  
  5845. -    if (time_adjust)
  5846. -    {
  5847. +    if (time_adjust) {
  5848.          /* We are doing an adjtime thing. 
  5849.           *
  5850.           * Modify the value of the tick for next time.
  5851. @@ -685,7 +722,7 @@
  5852.      calc_load();
  5853.      if (user_mode(regs)) {
  5854.          current->utime++;
  5855. -        if (current != task[0]) {
  5856. +        if (current->pid) {
  5857.              if (current->priority < 15)
  5858.                  kstat.cpu_nice++;
  5859.              else
  5860. @@ -698,9 +735,9 @@
  5861.          }
  5862.      } else {
  5863.          current->stime++;
  5864. -        if(current != task[0])
  5865. +        if(current->pid)
  5866.              kstat.cpu_system++;
  5867. -        if (prof_buffer && current != task[0]) {
  5868. +        if (prof_buffer && current->pid) {
  5869.              extern int _stext;
  5870.              unsigned long ip = instruction_pointer(regs);
  5871.              ip -= (unsigned long) &_stext;
  5872. @@ -727,7 +764,7 @@
  5873.              send_sig(SIGXCPU, current, 1);
  5874.      }
  5875.  
  5876. -    if (current != task[0] && 0 > --current->counter) {
  5877. +    if (current->pid && 0 > --current->counter) {
  5878.          current->counter = 0;
  5879.          need_resched = 1;
  5880.      }
  5881. @@ -875,6 +912,15 @@
  5882.  
  5883.  void sched_init(void)
  5884.  {
  5885. +    /*
  5886. +     *    We have to do a little magic to get the first
  5887. +     *    process right in SMP mode.
  5888. +     */
  5889. +    int cpu=smp_processor_id();
  5890. +    current_set[cpu]=&init_task;
  5891. +#ifdef CONFIG_SMP    
  5892. +    init_task.processor=cpu;
  5893. +#endif
  5894.      bh_base[TIMER_BH].routine = timer_bh;
  5895.      bh_base[TQUEUE_BH].routine = tqueue_bh;
  5896.      bh_base[IMMEDIATE_BH].routine = immediate_bh;
  5897. diff -u --recursive --new-file v1.3.30/linux/kernel/sys.c linux/kernel/sys.c
  5898. --- v1.3.30/linux/kernel/sys.c    Mon Sep 18 14:54:10 1995
  5899. +++ linux/kernel/sys.c    Mon Oct  2 14:25:12 1995
  5900. @@ -173,7 +173,7 @@
  5901.      if (C_A_D)
  5902.          hard_reset_now();
  5903.      else
  5904. -        send_sig(SIGINT,task[1],1);
  5905. +        kill_proc(1, SIGINT, 1);
  5906.  }
  5907.      
  5908.  
  5909. diff -u --recursive --new-file v1.3.30/linux/kernel/time.c linux/kernel/time.c
  5910. --- v1.3.30/linux/kernel/time.c    Wed Sep 27 16:00:00 1995
  5911. +++ linux/kernel/time.c    Mon Oct  2 08:21:27 1995
  5912. @@ -26,6 +26,8 @@
  5913.  #include <linux/mm.h>
  5914.  #include <linux/timex.h>
  5915.  
  5916. +#include <asm/segment.h>
  5917. +
  5918.  /* 
  5919.   * The timezone where the local system is located.  Used as a default by some
  5920.   * programs who obtain this value by using gettimeofday.
  5921. diff -u --recursive --new-file v1.3.30/linux/net/Changes linux/net/Changes
  5922. --- v1.3.30/linux/net/Changes    Wed Sep 27 16:00:01 1995
  5923. +++ linux/net/Changes    Wed Oct  4 08:15:11 1995
  5924. @@ -230,6 +230,19 @@
  5925.  o    TCP cache zap bugs hopefully fixed        [IN]
  5926.  o    Length checks in udp/raw sending [Craig Metz]    [IN]
  5927.  
  5928. +-------->>>>> 1.3.31 <<<<<<-------
  5929. +
  5930. +o    IP_OPTIONS [A.N.Kuznetsov]            [IN]
  5931. +o    TCP cache zap more fixes            [IN]
  5932. +o    Most of the IP multicast routing cache added    [IN]
  5933. +o    Kernel/user communication module (not used yet) [IN]
  5934. +
  5935. +-------->>>>> 1.3.31 <<<<<<-------
  5936. +
  5937. +o    IFF_ALLMULTI support for 3c501,3c509,8390 and
  5938. +    tulip(SMC etherpower) boards            [IN]
  5939. +
  5940. +
  5941.  ---------- Things I thought Linus had for a while and not merged ----------------
  5942.  
  5943.  o    Paul Gortmakers 8390 Copy and checksum        [Pending]
  5944. @@ -240,19 +253,15 @@
  5945.  ---------- Things pending for me to merge --------------
  5946.  
  5947.  o    IPFW support for TOS changing (Al Longyear)
  5948. -o    /dev/skip /dev/ipah etc - Kernel/Usermode communications module (me)
  5949.  o    AF_UNIX garbage collect code
  5950.  o    Faster closedown option for heavy use sites (me)
  5951.  o    Tom May's insw_and_checksum()            
  5952.  
  5953. -
  5954. -
  5955. ---------------- Tbings That Need Doing Before 1.4 ------------------
  5956. +--------------- Things That Need Doing Before 1.4 ------------------
  5957.  
  5958.  o    inet_error for other layers
  5959.  o    Finish merging the bridge code
  5960.  o    SIOCSLEEPRT patch
  5961. -o    Options support in ip_build_xmit        [PENDING]
  5962.  o    Fast checksum/copy on outgoing TCP
  5963.  o    Fast dev_grab_next() transmit reload function
  5964.      and dev_push_failed() ??
  5965. @@ -261,10 +270,8 @@
  5966.  o    Forwarding queue control (+ fairness algorithms ??)
  5967.  o    IP forward flow control.
  5968.  o    Infinite PPP devices.
  5969. -o    AX.25 set protocol type
  5970.  o    Clean up RAW AX.25 sockets.
  5971.  o    Finish 802.2 Class I code to be compliant to the oddities of 802.2
  5972. -o    Full variable length AX.25 support        [JSN doing]
  5973.  o    Tidy BPQ support to use a bpqip tunnel device
  5974.  o    Strange eth0-eth3 bug 
  5975.  o    Finish IPIP bug fixes                [Done hopefully]
  5976. @@ -276,9 +283,7 @@
  5977.  
  5978.  0.2
  5979.  ---
  5980. -o    New icmp.c.                    [IN]
  5981.  o    Better TCP window handling [Pedro Roque]
  5982. -o    IP option support.
  5983.  o    Add tty support to sonix driver.
  5984.  o    PPP for Sonix ISDN.
  5985.  o    Loadable firewall extensions.
  5986. diff -u --recursive --new-file v1.3.30/linux/net/Makefile linux/net/Makefile
  5987. --- v1.3.30/linux/net/Makefile    Fri Aug 18 08:44:58 1995
  5988. +++ linux/net/Makefile    Mon Oct  2 14:25:12 1995
  5989. @@ -11,6 +11,6 @@
  5990.  ALL_SUB_DIRS := 802 ax25 core ethernet ipv4 ipx unix appletalk netrom
  5991.  SUB_DIRS     := $(ALL_SUB_DIRS)
  5992.  L_TARGET     := network.a
  5993. -L_OBJS         := socket.o protocols.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
  5994. +L_OBJS         := socket.o protocols.o netlink.o $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
  5995.  
  5996.  include $(TOPDIR)/Rules.make
  5997. diff -u --recursive --new-file v1.3.30/linux/net/ipv4/Makefile linux/net/ipv4/Makefile
  5998. --- v1.3.30/linux/net/ipv4/Makefile    Wed Sep 27 16:00:01 1995
  5999. +++ linux/net/ipv4/Makefile    Wed Oct  4 08:22:36 1995
  6000. @@ -17,8 +17,10 @@
  6001.  
  6002.  ifeq ($(CONFIG_INET_RARP),y)
  6003.  IPV4_OBJS += rarp.o
  6004. -elifeq ($(CONFIG_INET_RARP),m)
  6005. -M_OBJS += rarp.o
  6006. +else
  6007. +  ifeq ($(CONFIG_INET_RARP),m)
  6008. +  M_OBJS += rarp.o
  6009. +  endif
  6010.  endif
  6011.  
  6012.  ifeq ($(CONFIG_NET_IPIP),y)
  6013. diff -u --recursive --new-file v1.3.30/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
  6014. --- v1.3.30/linux/net/ipv4/icmp.c    Wed Sep 27 16:00:01 1995
  6015. +++ linux/net/ipv4/icmp.c    Tue Oct  3 11:40:56 1995
  6016. @@ -196,31 +196,29 @@
  6017.   
  6018.  static void icmp_glue_bits(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
  6019.  {
  6020. -    struct icmp_bxm *icmp_param=(struct icmp_bxm *)p;
  6021. +    struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
  6022.      struct icmphdr *icmph;
  6023. -    if(offset)
  6024. +    unsigned long csum;
  6025. +
  6026. +    if (offset) {
  6027.          icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr), 
  6028.                  to, fraglen,icmp_param->csum);
  6029. -    else
  6030. -    {
  6031. -#ifdef CSUM_FOLD_WORKS
  6032. -        /*
  6033. -         *    Need this fixed to make multifragment ICMP's work again.
  6034. -         */
  6035. -        icmp_param->csum=csum_partial_copy((void *)&icmp_param->icmph, to, sizeof(struct icmphdr),
  6036. -            icmp_param->csum);
  6037. -        icmp_param->csum=csum_partial_copy(icmp_param->data_ptr, to+sizeof(struct icmphdr),
  6038. -                fraglen-sizeof(struct icmphdr), icmp_param->csum);
  6039. -        icmph=(struct icmphdr *)to;
  6040. -        icmph->checksum = csum_fold(icmp_param->csum);
  6041. -#else
  6042. -        memcpy(to, &icmp_param->icmph, sizeof(struct icmphdr));
  6043. -        memcpy(to+sizeof(struct icmphdr), icmp_param->data_ptr, fraglen-sizeof(struct icmphdr));
  6044. -        icmph=(struct icmphdr *)to;
  6045. -        icmph->checksum=ip_compute_csum(to, fraglen);
  6046. -#endif
  6047. -                
  6048. +        return;
  6049.      }
  6050. +
  6051. +    /*
  6052. +     *    First fragment includes header. Note that we've done
  6053. +     *    the other fragments first, so that we get the checksum
  6054. +     *    for the whole packet here.
  6055. +     */
  6056. +    csum = csum_partial_copy((void *)&icmp_param->icmph,
  6057. +        to, sizeof(struct icmphdr), 
  6058. +        icmp_param->csum);
  6059. +    csum = csum_partial_copy(icmp_param->data_ptr,
  6060. +        to+sizeof(struct icmphdr),
  6061. +        fraglen-sizeof(struct icmphdr), csum);
  6062. +    icmph=(struct icmphdr *)to;
  6063. +    icmph->checksum = csum_fold(csum);
  6064.  }
  6065.   
  6066.  /*
  6067. @@ -231,6 +229,7 @@
  6068.  {
  6069.      struct sock *sk=icmp_socket.data;
  6070.      icmp_param->icmph.checksum=0;
  6071. +    icmp_param->csum=0;
  6072.      icmp_out_count(icmp_param->icmph.type);
  6073.      ip_build_xmit(sk, icmp_glue_bits, icmp_param, 
  6074.          icmp_param->data_len+sizeof(struct icmphdr),
  6075. @@ -698,10 +697,12 @@
  6076.  void icmp_init(struct proto_ops *ops)
  6077.  {
  6078.      struct sock *sk;
  6079. +    int err;
  6080.      icmp_socket.type=SOCK_RAW;
  6081.      icmp_socket.ops=ops;
  6082. -    if(ops->create(&icmp_socket, IPPROTO_ICMP)<0)
  6083. -        panic("Failed to create the ICMP control socket.\n");
  6084. +    if((err=ops->create(&icmp_socket, IPPROTO_ICMP))<0)
  6085. +        panic("Failed to create the ICMP control socket (%d,%d,%p,%p).\n", -err,
  6086. +            current->euid, current, &init_task);
  6087.      sk=icmp_socket.data;
  6088.      sk->allocation=GFP_ATOMIC;
  6089.      sk->num = 256;            /* Don't receive any data */
  6090. diff -u --recursive --new-file v1.3.30/linux/net/ipv4/ip.c linux/net/ipv4/ip.c
  6091. --- v1.3.30/linux/net/ipv4/ip.c    Wed Sep 27 16:00:02 1995
  6092. +++ linux/net/ipv4/ip.c    Wed Oct  4 08:15:11 1995
  6093. @@ -93,6 +93,8 @@
  6094.   *    Werner Almesberger    :    Zero fragment bug
  6095.   *        Alan Cox    :    RAW IP frame length bug
  6096.   *        Alan Cox    :    Outgoing firewall on build_xmit
  6097. + *        A.N.Kuznetsov    :    IP_OPTIONS support throughout the kernel
  6098. + *        Alan Cox    :    Multicast routing hooks
  6099.   *
  6100.   *  
  6101.   *
  6102. @@ -1466,6 +1468,50 @@
  6103.  
  6104.  
  6105.  #ifdef CONFIG_IP_FORWARD
  6106. +#ifdef CONFIG_IP_MROUTE
  6107. +
  6108. +/*
  6109. + *     Encapsulate a packet by attaching a valid IPIP header to it.
  6110. + *    This avoids tunnel drivers and other mess and gives us the speed so
  6111. + *    important for multicast video.
  6112. + */
  6113. +static void ip_encap(struct sk_buff *skb, int len, struct device *out, __u32 daddr)
  6114. +{
  6115. +    /*
  6116. +     *    There is space for the IPIP header and MAC left.
  6117. +     *
  6118. +     *    Firstly push down and install the IPIP header.
  6119. +     */
  6120. +    struct iphdr *iph=(struct iphdr *)skb_push(skb,sizeof(struct iphdr));
  6121. +    if(len>65515)
  6122. +        len=65515;
  6123. +    iph->version    =     4;
  6124. +    iph->tos    =    skb->ip_hdr->tos;
  6125. +    iph->ttl    =    skb->ip_hdr->ttl;
  6126. +    iph->frag_off    =    0;
  6127. +    iph->daddr    =    daddr;
  6128. +    iph->saddr    =    out->pa_addr;
  6129. +    iph->protocol    =    IPPROTO_IPIP;
  6130. +    iph->ihl    =    5;
  6131. +    iph->tot_len    =    htons(skb->len);
  6132. +    iph->id        =    htons(ip_id_count++);
  6133. +    ip_send_check(iph);
  6134. +
  6135. +    skb->dev = out;
  6136. +    skb->arp = 1;
  6137. +    skb->raddr=daddr;
  6138. +    /*
  6139. +     *    Now add the physical header (driver will push it down).
  6140. +     */
  6141. +    if (out->hard_header && out->hard_header(skb, out, ETH_P_IP, NULL, NULL, len)<0)
  6142. +            skb->arp=0;
  6143. +    /*
  6144. +     *    Read to queue for transmission.
  6145. +     */
  6146. +}
  6147. +
  6148. +#endif
  6149.  
  6150.  /*
  6151.   *    Forward an IP datagram to its next destination.
  6152. @@ -1485,7 +1531,8 @@
  6153.      int fw_res = 0;        /* Forwarding result */    
  6154.  #ifdef CONFIG_IP_MASQUERADE    
  6155.      struct sk_buff *skb_in = skb;    /* So we can remember if the masquerader did some swaps */
  6156. -#endif    
  6157. +#endif
  6158. +    int encap = 0;        /* Encap length */
  6159.      
  6160.      /* 
  6161.       *    See if we are allowed to forward this.
  6162. @@ -1542,83 +1589,86 @@
  6163.          return -1;
  6164.      }
  6165.  
  6166. -    /*
  6167. -     * OK, the packet is still valid.  Fetch its destination address,
  6168. -     * and give it to the IP sender for further processing.
  6169. -     */
  6170. -
  6171. -    rt = ip_rt_route(target_addr, NULL, NULL);
  6172. -    if (rt == NULL)
  6173. -    {
  6174. -        /*
  6175. -         *    Tell the sender its packet cannot be delivered. Again
  6176. -         *    ICMP is screened later.
  6177. -         */
  6178. -        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
  6179. -        return -1;
  6180. -    }
  6181. -
  6182. -
  6183. -    /*
  6184. -     * Gosh.  Not only is the packet valid; we even know how to
  6185. -     * forward it onto its final destination.  Can we say this
  6186. -     * is being plain lucky?
  6187. -     * If the router told us that there is no GW, use the dest.
  6188. -     * IP address itself- we seem to be connected directly...
  6189. -     */
  6190. -
  6191. -    raddr = rt->rt_gateway;
  6192. -
  6193. -    if (raddr != 0)
  6194. +#ifdef CONFIG_IP_MROUTE
  6195. +    if(!(is_frag&8))
  6196.      {
  6197. +#endif    
  6198.          /*
  6199. -         *    Strict routing permits no gatewaying
  6200. +         * OK, the packet is still valid.  Fetch its destination address,
  6201. +         * and give it to the IP sender for further processing.
  6202.           */
  6203.  
  6204. -            if (opt->is_strictroute)
  6205. +        rt = ip_rt_route(target_addr, NULL, NULL);
  6206. +        if (rt == NULL)
  6207.          {
  6208. -            icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
  6209. +            /*
  6210. +             *    Tell the sender its packet cannot be delivered. Again
  6211. +             *    ICMP is screened later.
  6212. +             */
  6213. +            icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);
  6214.              return -1;
  6215.          }
  6216.      
  6217. +    
  6218.          /*
  6219. -         *    There is a gateway so find the correct route for it.
  6220. -         *    Gateways cannot in turn be gatewayed.
  6221. +         * Gosh.  Not only is the packet valid; we even know how to
  6222. +         * forward it onto its final destination.  Can we say this
  6223. +         * is being plain lucky?
  6224. +         * If the router told us that there is no GW, use the dest.
  6225. +         * IP address itself- we seem to be connected directly...
  6226.           */
  6227.  
  6228. -#if 0
  6229. -        rt = ip_rt_route(raddr, NULL, NULL);
  6230. -        if (rt == NULL)
  6231. +        raddr = rt->rt_gateway;
  6232. +    
  6233. +        if (raddr != 0)
  6234.          {
  6235.              /*
  6236. -             *    Tell the sender its packet cannot be delivered...
  6237. +             *    Strict routing permits no gatewaying
  6238. +             */
  6239. +    
  6240. +                if (opt->is_strictroute)
  6241. +            {
  6242. +                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0, dev);
  6243. +                return -1;
  6244. +            }
  6245. +        
  6246. +            /*
  6247. +             *    There is a gateway so find the correct route for it.
  6248. +             *    Gateways cannot in turn be gatewayed.
  6249.               */
  6250. -            icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
  6251. -            return -1;
  6252.          }
  6253. -        if (rt->rt_gateway != 0)
  6254. -            raddr = rt->rt_gateway;
  6255. +        else
  6256. +            raddr = target_addr;
  6257. +
  6258. +        /*
  6259. +         *    Having picked a route we can now send the frame out.
  6260. +         */
  6261. +
  6262. +        dev2 = rt->rt_dev;
  6263. +        /*
  6264. +         *    In IP you never have to forward a frame on the interface that it 
  6265. +         *    arrived upon. We now generate an ICMP HOST REDIRECT giving the route
  6266. +         *    we calculated.
  6267. +         */
  6268. +#ifndef CONFIG_IP_NO_ICMP_REDIRECT
  6269. +        if (dev == dev2 && !((iph->saddr^iph->daddr)&dev->pa_mask) &&
  6270. +            (rt->rt_flags&RTF_MODIFIED) && !opt->srr)
  6271. +            icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
  6272.  #endif
  6273. +#ifdef CONFIG_IP_MROUTE
  6274.      }
  6275.      else
  6276. -        raddr = target_addr;
  6277. -
  6278. -    /*
  6279. -     *    Having picked a route we can now send the frame out.
  6280. -     */
  6281. -
  6282. -    dev2 = rt->rt_dev;
  6283. +    {
  6284. +        /*
  6285. +         *    Multicast route forward. Routing is already done
  6286. +         */
  6287. +        dev2=skb->dev;
  6288. +        raddr=skb->raddr;
  6289. +        if(is_frag&16)        /* VIFF_TUNNEL mode */
  6290. +            encap=20;
  6291. +    }
  6292. +#endif    
  6293.      
  6294. -    /*
  6295. -     *    In IP you never have to forward a frame on the interface that it 
  6296. -     *    arrived upon. We now generate an ICMP HOST REDIRECT giving the route
  6297. -     *    we calculated.
  6298. -     */
  6299. -#ifndef CONFIG_IP_NO_ICMP_REDIRECT
  6300. -    if (dev == dev2 && !((iph->saddr^iph->daddr)&dev->pa_mask) &&
  6301. -        (rt->rt_flags&RTF_MODIFIED) && !opt->srr)
  6302. -        icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
  6303. -#endif        
  6304.  
  6305.      /*
  6306.       * We now may allocate a new buffer, and copy the datagram into it.
  6307. @@ -1637,17 +1687,21 @@
  6308.  #endif
  6309.          IS_SKB(skb);
  6310.  
  6311. -        if (skb->len > dev2->mtu && (ntohs(iph->frag_off) & IP_DF)) {
  6312. +        if (skb->len+encap > dev2->mtu && (ntohs(iph->frag_off) & IP_DF)) {
  6313.            ip_statistics.IpFragFails++;
  6314.            icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev2->mtu, dev);
  6315.            return -1;
  6316.          }
  6317.  
  6318. +#ifdef CONFIG_IP_MROUTE
  6319. +        if(skb_headroom(skb)-encap<dev2->hard_header_len)
  6320. +        {
  6321. +            skb2 = alloc_skb(dev2->hard_header_len + skb->len + encap + 15, GFP_ATOMIC);
  6322. +#else
  6323.          if(skb_headroom(skb)<dev2->hard_header_len)
  6324.          {
  6325.              skb2 = alloc_skb(dev2->hard_header_len + skb->len + 15, GFP_ATOMIC);
  6326. -            IS_SKB(skb2);
  6327. -        
  6328. +#endif        
  6329.              /*
  6330.               *    This is rare and since IP is tolerant of network failures
  6331.               *    quite harmless.
  6332. @@ -1659,11 +1713,19 @@
  6333.                  return -1;
  6334.              }
  6335.          
  6336. +            IS_SKB(skb2);
  6337.              /*
  6338.               *    Add the physical headers.
  6339.               */
  6340. -
  6341. -             ip_send(skb2,raddr,skb->len,dev2,dev2->pa_addr);
  6342. +#ifdef CONFIG_IP_MROUTE
  6343. +            if(is_frag&16)
  6344. +            {
  6345. +                skb_reserve(skb,(encap+dev->hard_header_len+15)&~15);    /* 16 byte aligned IP headers are good */
  6346. +                ip_encap(skb2,skb->len, dev2, raddr);
  6347. +            }
  6348. +            else
  6349. +#endif            
  6350. +                 ip_send(skb2,raddr,skb->len,dev2,dev2->pa_addr);
  6351.  
  6352.              /*
  6353.               *    We have to copy the bytes over as the new header wouldn't fit
  6354. @@ -1689,13 +1751,22 @@
  6355.  
  6356.              skb2 = skb;        
  6357.              skb2->dev=dev2;
  6358. -            skb->arp=1;
  6359. -            skb->raddr=raddr;
  6360. -            if(dev2->hard_header)
  6361. +#ifdef CONFIG_IP_MROUTE
  6362. +            if(is_frag&16)
  6363. +                ip_encap(skb,skb->len, dev2, raddr);
  6364. +            else
  6365.              {
  6366. -                if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0)
  6367. -                    skb->arp=0;
  6368. -            }
  6369. +#endif
  6370. +                skb->arp=1;
  6371. +                skb->raddr=raddr;
  6372. +                if(dev2->hard_header)
  6373. +                {
  6374. +                    if(dev2->hard_header(skb, dev2, ETH_P_IP, NULL, NULL, skb->len)<0)
  6375. +                        skb->arp=0;
  6376. +                }
  6377. +#ifdef CONFIG_IP_MROUTE
  6378. +            }                
  6379. +#endif            
  6380.              ip_statistics.IpForwDatagrams++;
  6381.          }
  6382.  
  6383. @@ -1825,6 +1896,9 @@
  6384.  #ifdef CONFIG_IP_FIREWALL
  6385.      int err;
  6386.  #endif    
  6387. +#ifdef CONFIG_IP_MROUTE
  6388. +    int mroute_pkt=0;
  6389. +#endif    
  6390.  
  6391.  #ifdef CONFIG_NET_IPV6
  6392.      /* 
  6393. @@ -1944,9 +2018,11 @@
  6394.              for ( srrptr=optptr[2], srrspace = optptr[1];
  6395.                    srrptr <= srrspace;
  6396.                    srrptr += 4
  6397. -                 ) {
  6398. +                 ) 
  6399. +            {
  6400.                  int brd2;
  6401. -                if (srrptr + 3 > srrspace) {
  6402. +                if (srrptr + 3 > srrspace) 
  6403. +                {
  6404.                      icmp_send(skb, ICMP_PARAMETERPROB, 0, opt->srr+2,
  6405.                            skb->dev);
  6406.                      kfree_skb(skb, FREE_WRITE);
  6407. @@ -1954,21 +2030,26 @@
  6408.                  }
  6409.                  memcpy(&nexthop, &optptr[srrptr-1], 4);
  6410.                  if ((brd2 = ip_chk_addr(nexthop)) == 0)
  6411. -                  break;
  6412. -                if (brd2 != IS_MYADDR) {
  6413. -/* ANK: should we implement weak tunneling of multicasts?
  6414. - *    Are they obsolete? DVMRP specs (RFC-1075) is old enough...
  6415. - */
  6416. +                    break;
  6417. +                if (brd2 != IS_MYADDR) 
  6418. +                {
  6419. +
  6420. +                    /*
  6421. +                     *    ANK: should we implement weak tunneling of multicasts?
  6422. +                     *    Are they obsolete? DVMRP specs (RFC-1075) is old enough...
  6423. +                     *    [They are obsolete]
  6424. +                     */
  6425.                      kfree_skb(skb, FREE_WRITE);
  6426.                      return -EINVAL;
  6427.                  }
  6428.              }
  6429. -            if (srrptr <= srrspace) {
  6430. +            if (srrptr <= srrspace) 
  6431. +            {
  6432.                  opt->srr_is_hit = 1;
  6433.                  opt->is_changed = 1;
  6434.  #ifdef CONFIG_IP_FORWARD
  6435.                  if (ip_forward(skb, dev, is_frag, nexthop))
  6436. -                  kfree_skb(skb, FREE_WRITE);
  6437. +                    kfree_skb(skb, FREE_WRITE);
  6438.  #else
  6439.                  ip_statistics.IpInAddrErrors++;
  6440.                  kfree_skb(skb, FREE_WRITE);
  6441. @@ -2041,6 +2122,15 @@
  6442.          skb->ip_hdr = iph;
  6443.          skb->h.raw += iph->ihl*4;
  6444.  
  6445. +#ifdef CONFIG_IP_MROUTE        
  6446. +        /*
  6447. +         *    Check the state on multicast routing (multicast and not 224.0.0.z)
  6448. +         */
  6449. +         
  6450. +        if(brd==IS_MULTICAST && (iph->daddr&htonl(0xFFFFFF00))!=htonl(0xE0000000))
  6451. +            mroute_pkt=1;
  6452. +
  6453. +#endif
  6454.          /*
  6455.           *    Deliver to raw sockets. This is fun as to avoid copies we want to make no surplus copies.
  6456.           *
  6457. @@ -2102,7 +2192,11 @@
  6458.              *    raw delivery wait for that
  6459.              */
  6460.      
  6461. +#ifdef CONFIG_IP_MROUTE
  6462. +            if (ipprot->copy || raw_sk || mroute_pkt)
  6463. +#else    
  6464.              if (ipprot->copy || raw_sk)
  6465. +#endif            
  6466.              {
  6467.                  skb2 = skb_clone(skb, GFP_ATOMIC);
  6468.                  if(skb2==NULL)
  6469. @@ -2132,6 +2226,30 @@
  6470.           *    ICMP reply messages get queued up for transmission...)
  6471.           */
  6472.  
  6473. +#ifdef CONFIG_IP_MROUTE         
  6474. +        /*
  6475. +         *    Forward the last copy to the multicast router. If
  6476. +         *    there is a pending raw deliery however make a copy
  6477. +         *    and forward that.
  6478. +         */
  6479. +         
  6480. +        if(mroute_pkt)
  6481. +        {
  6482. +            flag=1;
  6483. +            if(raw_sk==NULL)
  6484. +                ipmr_forward(skb, is_frag);
  6485. +            else
  6486. +            {
  6487. +                struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
  6488. +                if(skb2)
  6489. +                {
  6490. +                    skb2->free=1;
  6491. +                    ipmr_forward(skb2, is_frag);
  6492. +                }
  6493. +            }
  6494. +        }
  6495. +#endif        
  6496. +
  6497.          if(raw_sk!=NULL)    /* Shift to last raw user */
  6498.              raw_rcv(raw_sk, skb, dev, iph->saddr, iph->daddr);
  6499.          else if (!flag)        /* Free and report errors */
  6500. @@ -2145,7 +2263,7 @@
  6501.      }
  6502.  
  6503.      /*
  6504. -     *    Do any IP forwarding required.
  6505. +     *    Do any unicast IP forwarding required.
  6506.       */
  6507.      
  6508.      /*
  6509. @@ -2266,14 +2384,7 @@
  6510.       *    header length problem
  6511.       */
  6512.  
  6513. -#if 0
  6514. -    ptr = skb->data;
  6515. -    ptr += dev->hard_header_len;
  6516. -    iph = (struct iphdr *)ptr;    
  6517. -    skb->ip_hdr = iph;
  6518. -#else
  6519.      iph = skb->ip_hdr;
  6520. -#endif
  6521.      iph->tot_len = ntohs(skb->len-(((unsigned char *)iph)-skb->data));
  6522.  
  6523.  #ifdef CONFIG_IP_FIREWALL
  6524. diff -u --recursive --new-file v1.3.30/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
  6525. --- v1.3.30/linux/net/ipv4/ip_fw.c    Wed Sep 13 12:45:35 1995
  6526. +++ linux/net/ipv4/ip_fw.c    Wed Oct  4 08:15:11 1995
  6527. @@ -40,6 +40,7 @@
  6528.   *    Alan Cox        :    Fixed an error in the merge.
  6529.   *    Thomas Quinot        :    Fixed port spoofing.
  6530.   *    Alan Cox        :    Cleaned up retransmits in spoofing.
  6531. + *    Alan Cox        :    Cleaned up length setting.
  6532.   *
  6533.   *    All the real work was done by .....
  6534.   *
  6535. @@ -266,7 +267,7 @@
  6536.          case IPPROTO_TCP:
  6537.              dprintf1("TCP ");
  6538.              /* ports stay 0 if it is not the first fragment */
  6539. -            if (offset!=0) {
  6540. +            if (!offset) {
  6541.                  src_port=ntohs(tcp->source);
  6542.                  dst_port=ntohs(tcp->dest);
  6543.                  if(tcp->ack)
  6544. @@ -281,7 +282,7 @@
  6545.          case IPPROTO_UDP:
  6546.              dprintf1("UDP ");
  6547.              /* ports stay 0 if it is not the first fragment */
  6548. -            if (offset!=0) {
  6549. +            if (!offset) {
  6550.                  src_port=ntohs(udp->source);
  6551.                  dst_port=ntohs(udp->dest);
  6552.              }
  6553. @@ -700,6 +701,12 @@
  6554.  /*         skb2->h.raw = &skb2->data[skb->h.raw - skb->data];*/
  6555.          skb2->h.raw = skb2->data + (skb->h.raw - skb->data);
  6556.          iph=skb2->h.iph;
  6557. +        /*
  6558. +         *    Mend the IP header too
  6559. +         */
  6560. +        iph->tot_len = htons(diff+ntohs(iph->tot_len));
  6561. +        iph->check = 0;
  6562. +        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
  6563.   
  6564.           /*
  6565.            *    Copy the packet data into the new buffer.
  6566. diff -u --recursive --new-file v1.3.30/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
  6567. --- v1.3.30/linux/net/ipv4/ipmr.c    Wed Sep 27 16:00:02 1995
  6568. +++ linux/net/ipv4/ipmr.c    Wed Oct  4 08:15:11 1995
  6569. @@ -12,10 +12,16 @@
  6570.   *
  6571.   *    Fixes:
  6572.   *    Michael Chastain    :    Incorrect size of copying.
  6573. - *
  6574. + *    Alan Cox        :    Added the cache manager code
  6575.   *
  6576.   *    Status:
  6577. - *        Tree building works. Cache manager to be added next.
  6578. + *        Cache manager under test. Forwarding in vague test mode
  6579. + *    Todo:
  6580. + *        Flow control
  6581. + *        Tunnels
  6582. + *        Wipe cache on mrouted exit
  6583. + *        Debug cache ttl handling properly
  6584. + *        Resolve IFF_ALLMULTI for most cards
  6585.   */
  6586.  
  6587.  #include <asm/system.h>
  6588. @@ -27,10 +33,12 @@
  6589.  #include <linux/mm.h>
  6590.  #include <linux/kernel.h>
  6591.  #include <linux/fcntl.h>
  6592. +#include <linux/stat.h>
  6593.  #include <linux/socket.h>
  6594.  #include <linux/in.h>
  6595.  #include <linux/inet.h>
  6596.  #include <linux/netdevice.h>
  6597. +#include <linux/proc_fs.h>
  6598.  #include <linux/mroute.h>
  6599.  #include <net/ip.h>
  6600.  #include <net/protocol.h>
  6601. @@ -47,9 +55,12 @@
  6602.   *    Multicast router conrol variables
  6603.   */
  6604.  
  6605. -static struct vif_device vif_table[MAXVIFS];
  6606. -static unsigned long vifc_map;
  6607. -int mroute_do_pim = 0;
  6608. +static struct vif_device vif_table[MAXVIFS];        /* Devices         */
  6609. +static unsigned long vifc_map;                /* Active device map    */
  6610. +int mroute_do_pim = 0;                    /* Set in PIM assert    */
  6611. +static struct mfc_cache *mfc_cache_array[MFC_LINES];    /* Forwarding cache    */
  6612. +static struct mfc_cache *cache_resolve_queue;        /* Unresolved cache    */
  6613. +int cache_resolve_queue_len = 0;            /* Size of unresolved    */
  6614.  
  6615.  /*
  6616.   *    Delete a VIF entry
  6617. @@ -64,6 +75,342 @@
  6618.      }
  6619.      v->dev=NULL;
  6620.  }
  6621. +
  6622. +/*
  6623. + *    Find a vif
  6624. + */
  6625. +static int ipmr_vifi_find(struct device *dev)
  6626. +{
  6627. +    struct vif_device *v=&vif_table[0];
  6628. +    int ct;
  6629. +    for(ct=0;ct<MAXVIFS;ct++,v++)
  6630. +    {
  6631. +        if(v->dev==dev)
  6632. +            return ct;
  6633. +    }
  6634. +    return -1;
  6635. +}
  6636. +
  6637. +/*
  6638. + *    Delete a multicast route cache entry
  6639. + */
  6640. +static void ipmr_cache_delete(struct mfc_cache *cache)
  6641. +{
  6642. +    struct sk_buff *skb;
  6643. +    int line;
  6644. +    struct mfc_cache **cp;
  6645. +    
  6646. +    /*
  6647. +     *    Find the right cache line
  6648. +     */
  6649. +
  6650. +    if(cache->mfc_flags&MFC_QUEUED)
  6651. +    {    
  6652. +        cp=&cache_resolve_queue;
  6653. +        del_timer(&cache->mfc_timer);
  6654. +    }    
  6655. +    else
  6656. +    {
  6657. +        line=MFC_HASH(cache->mfc_mcastgrp,cache->mfc_origin);
  6658. +        cp=&(mfc_cache_array[line]);
  6659. +    }
  6660. +    
  6661. +    /*
  6662. +     *    Unlink the buffer
  6663. +     */
  6664. +    
  6665. +    while(*cp!=NULL)
  6666. +    {
  6667. +        if(*cp==cache)
  6668. +        {
  6669. +            *cp=cache->next;
  6670. +            break;
  6671. +        }
  6672. +        cp=&((*cp)->next);
  6673. +    }
  6674. +    
  6675. +    /*
  6676. +     *    Free the buffer. If it is a pending resolution
  6677. +     *    clean up the other resources.
  6678. +     */
  6679. +
  6680. +    if(cache->mfc_flags&MFC_QUEUED)
  6681. +    {
  6682. +        cache_resolve_queue_len--;
  6683. +        while((skb=skb_dequeue(&cache->mfc_unresolved)))
  6684. +            kfree_skb(skb, FREE_WRITE);
  6685. +    }
  6686. +    kfree_s(cache,sizeof(cache));
  6687. +}
  6688. +
  6689. +/*
  6690. + *    Cache expiry timer
  6691. + */    
  6692. +static void ipmr_cache_timer(unsigned long data)
  6693. +{
  6694. +    struct mfc_cache *cache=(struct mfc_cache *)data;
  6695. +    ipmr_cache_delete(cache);
  6696. +}
  6697. +
  6698. +/*
  6699. + *    Insert a multicast cache entry
  6700. + */
  6701. +
  6702. +static void ipmr_cache_insert(struct mfc_cache *c)
  6703. +{
  6704. +    int line=MFC_HASH(c->mfc_mcastgrp,c->mfc_origin);
  6705. +    c->next=mfc_cache_array[line];
  6706. +    mfc_cache_array[line]=c;
  6707. +}
  6708. +/*
  6709. + *    Find a multicast cache entry
  6710. + */
  6711. +struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp)
  6712. +{
  6713. +    int line=MFC_HASH(mcastgrp,origin);
  6714. +    struct mfc_cache *cache;
  6715. +    cache=mfc_cache_array[line];
  6716. +    while(cache!=NULL)
  6717. +    {
  6718. +        if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
  6719. +            return cache;
  6720. +        cache=cache->next;
  6721. +    }
  6722. +    cache=cache_resolve_queue;
  6723. +    while(cache!=NULL)
  6724. +    {
  6725. +        if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
  6726. +            return cache;
  6727. +        cache=cache->next;
  6728. +    }
  6729. +    return NULL;
  6730. +}
  6731. +
  6732. +/*
  6733. + *    Allocate a multicast cache entry
  6734. + */
  6735. +static struct mfc_cache *ipmr_cache_alloc(int priority)
  6736. +{
  6737. +    struct mfc_cache *c=(struct mfc_cache *)kmalloc(sizeof(struct mfc_cache), priority);
  6738. +    if(c==NULL)
  6739. +        return NULL;
  6740. +    c->mfc_queuelen=0;
  6741. +    skb_queue_head_init(&c->mfc_unresolved);
  6742. +    init_timer(&c->mfc_timer);
  6743. +    c->mfc_timer.data=(long)c;
  6744. +    c->mfc_timer.function=ipmr_cache_timer;
  6745. +    return c;
  6746. +}
  6747. +/*
  6748. + *    A cache entry has gone into a resolved state from queued
  6749. + */
  6750. +static void ipmr_cache_resolve(struct mfc_cache *cache)
  6751. +{
  6752. +    struct mfc_cache **p;
  6753. +    struct sk_buff *skb;
  6754. +    /*
  6755. +     *    Kill the queue entry timer.
  6756. +     */
  6757. +    del_timer(&cache->mfc_timer);
  6758. +    cache->mfc_flags&=~MFC_QUEUED;
  6759. +    /*
  6760. +     *    Remove from the resolve queue
  6761. +     */
  6762. +    p=&cache_resolve_queue;
  6763. +    while((*p)!=NULL)
  6764. +    {
  6765. +        if((*p)==cache)
  6766. +        {
  6767. +            *p=cache->next;
  6768. +            break;
  6769. +        }
  6770. +        p=&((*p)->next);
  6771. +    }
  6772. +    cache_resolve_queue_len--;
  6773. +    sti();
  6774. +    /*
  6775. +     *    Insert into the main cache
  6776. +     */
  6777. +    ipmr_cache_insert(cache);
  6778. +    /*
  6779. +     *    Play the pending entries through our router
  6780. +     */
  6781. +    while((skb=skb_dequeue(&cache->mfc_unresolved)))
  6782. +        ipmr_forward(skb, skb->protocol);
  6783. +}
  6784. +
  6785. +/*
  6786. + *    Bounce a cache query up to mrouted. We could use netlink for this but mrouted
  6787. + *    expects the following bizarre scheme..
  6788. + */
  6789. +static void ipmr_cache_report(struct sk_buff *pkt)
  6790. +{
  6791. +    struct sk_buff *skb=alloc_skb(128, GFP_ATOMIC);
  6792. +    int ihl=pkt->ip_hdr->ihl<<2;
  6793. +    struct igmphdr *igmp;
  6794. +    if(!skb)
  6795. +        return;
  6796. +        
  6797. +    skb->free=1;
  6798. +    
  6799. +    /*
  6800. +     *    Copy the IP header
  6801. +     */
  6802. +
  6803. +    skb->ip_hdr=(struct iphdr *)skb_put(skb,ihl);
  6804. +    skb->h.iph=skb->ip_hdr;
  6805. +    memcpy(skb->data,pkt->data,ihl);
  6806. +    skb->ip_hdr->protocol = 0;            /* Flag to the kernel this is a route add */
  6807. +    
  6808. +    /*
  6809. +     *    Add our header
  6810. +     */
  6811. +    
  6812. +    igmp=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
  6813. +    igmp->type    =    IGMPMSG_NOCACHE;        /* non IGMP dummy message */
  6814. +    igmp->code     =    0;
  6815. +    skb->ip_hdr->tot_len=htons(skb->len);            /* Fix the length */
  6816. +    
  6817. +    /*
  6818. +     *    Deliver to mrouted
  6819. +     */
  6820. +    if(sock_queue_rcv_skb(mroute_socket,skb)<0)
  6821. +    {
  6822. +        skb->sk=NULL;
  6823. +        kfree_skb(skb, FREE_READ);
  6824. +    }
  6825. +}
  6826. +        
  6827. +/*
  6828. + *    Queue a packet for resolution
  6829. + */
  6830. +static void ipmr_cache_unresolved(struct mfc_cache *cache, vifi_t vifi, struct sk_buff *skb, int is_frag)
  6831. +{
  6832. +    if(cache==NULL)
  6833. +    {    
  6834. +        /*
  6835. +         *    Create a new entry if allowable
  6836. +         */
  6837. +        if(cache_resolve_queue_len>=10 || (cache=ipmr_cache_alloc(GFP_ATOMIC))==NULL)
  6838. +        {
  6839. +            kfree_skb(skb, FREE_WRITE);
  6840. +            return;
  6841. +        }
  6842. +        /*
  6843. +         *    Fill in the new cache entry
  6844. +         */
  6845. +        cache->mfc_parent=vifi;
  6846. +        cache->mfc_origin=skb->ip_hdr->saddr;
  6847. +        cache->mfc_mcastgrp=skb->ip_hdr->daddr;
  6848. +        cache->mfc_flags=MFC_QUEUED;
  6849. +        /*
  6850. +         *    Link to the unresolved list
  6851. +         */
  6852. +        cache->next=cache_resolve_queue;
  6853. +        cache_resolve_queue=cache;
  6854. +        cache_resolve_queue_len++;
  6855. +        /*
  6856. +         *    Fire off the expiry timer
  6857. +         */
  6858. +        cache->mfc_timer.expires=jiffies+10*HZ;
  6859. +        add_timer(&cache->mfc_timer);
  6860. +        /*
  6861. +         *    Reflect first query at mrouted.
  6862. +         */
  6863. +        if(mroute_socket)
  6864. +            ipmr_cache_report(skb);
  6865. +    }
  6866. +    /*
  6867. +     *    See if we can append the packet
  6868. +     */
  6869. +    if(cache->mfc_queuelen>3)
  6870. +    {
  6871. +        kfree_skb(skb, FREE_WRITE);
  6872. +        return;
  6873. +    }
  6874. +    /*
  6875. +     *    Add to our 'pending' list. Cache the is_frag data
  6876. +     *    in skb->protocol now it is spare.
  6877. +     */
  6878. +    cache->mfc_queuelen++;
  6879. +    skb->protocol=is_frag;
  6880. +    skb_queue_tail(&cache->mfc_unresolved,skb);
  6881. +}
  6882. +
  6883. +/*
  6884. + *    MFC cache manipulation by user space mroute daemon
  6885. + */
  6886. +int ipmr_mfc_modify(int action, struct mfcctl *mfc)
  6887. +{
  6888. +    struct mfc_cache *cache;
  6889. +    if(!MULTICAST(mfc->mfcc_mcastgrp.s_addr))
  6890. +        return -EINVAL;
  6891. +    /*
  6892. +     *    Find the cache line
  6893. +     */
  6894. +    
  6895. +    cli();
  6896. +    cache=ipmr_cache_find(mfc->mfcc_origin.s_addr,mfc->mfcc_mcastgrp.s_addr);
  6897. +    
  6898. +    /*
  6899. +     *    Delete an entry
  6900. +     */
  6901. +    if(action==MRT_DEL_MFC)
  6902. +    {
  6903. +        if(cache)
  6904. +        {
  6905. +            ipmr_cache_delete(cache);
  6906. +            sti();
  6907. +            return 0;
  6908. +        }
  6909. +        return -ENOENT;
  6910. +    }
  6911. +    if(cache)
  6912. +    {
  6913. +        /*
  6914. +         *    Update the cache, see if it frees a pending queue
  6915. +         */
  6916. +
  6917. +        cache->mfc_flags|=MFC_RESOLVED;
  6918. +        memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
  6919. +         
  6920. +        /*
  6921. +         *    Check to see if we resolved a queued list. If so we
  6922. +         *    need to send on the frames and tidy up.
  6923. +         */
  6924. +         
  6925. +        if(cache->mfc_flags&MFC_QUEUED)
  6926. +            ipmr_cache_resolve(cache);    /* Unhook & send the frames */
  6927. +        sti();
  6928. +        return 0;
  6929. +    }
  6930. +    /*
  6931. +     *    Unsolicited update - thats ok add anyway.
  6932. +     */
  6933. +    sti();
  6934. +    cache=ipmr_cache_alloc(GFP_KERNEL);
  6935. +    if(cache==NULL)
  6936. +        return -ENOMEM;
  6937. +    cache->mfc_flags=MFC_RESOLVED;
  6938. +    cache->mfc_origin=mfc->mfcc_origin.s_addr;
  6939. +    cache->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
  6940. +    cache->mfc_parent=mfc->mfcc_parent;
  6941. +    memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
  6942. +    ipmr_cache_insert(cache);
  6943. +    return 0;
  6944. +}
  6945.   
  6946.  /*
  6947.   *    Socket options and virtual interface manipulation. The whole
  6948. @@ -76,6 +423,7 @@
  6949.  {
  6950.      int err;
  6951.      struct vifctl vif;
  6952. +    struct mfcctl mfc;
  6953.      
  6954.      if(optname!=MRT_INIT)
  6955.      {
  6956. @@ -184,7 +532,11 @@
  6957.           */
  6958.          case MRT_ADD_MFC:
  6959.          case MRT_DEL_MFC:
  6960. -            return -EOPNOTSUPP;
  6961. +            err=verify_area(VERIFY_READ, optval, sizeof(mfc));
  6962. +            if(err)
  6963. +                return err;
  6964. +            memcpy_fromfs(&mfc,optval, sizeof(mfc));
  6965. +            return ipmr_mfc_modify(optname, &mfc);
  6966.          /*
  6967.           *    Control PIM assert.
  6968.           */
  6969. @@ -301,6 +653,15 @@
  6970.          v++;
  6971.      }        
  6972.      vifc_map=0;    
  6973. +    /*
  6974. +     *    Wipe the cache
  6975. +     */
  6976. +    for(i=0;i<MFC_LINES;i++)
  6977. +    {
  6978. +        while(mfc_cache_array[i]!=NULL)
  6979. +            ipmr_cache_delete(mfc_cache_array[i]);
  6980. +    }    
  6981. +    /* The timer will clear any 'pending' stuff */
  6982.  }
  6983.  
  6984.  static int ipmr_device_event(unsigned long event, void *ptr)
  6985. @@ -328,12 +689,226 @@
  6986.      NULL,
  6987.      0
  6988.  };
  6989. +
  6990. +/*
  6991. + *    Processing handlers for ipmr_forward
  6992. + */
  6993. +
  6994. +static void ipmr_queue_xmit(struct sk_buff *skb, struct vif_device *vif, struct device *in_dev, int frag)
  6995. +{
  6996. +    int tunnel=0;
  6997. +    __u32 raddr=skb->raddr;
  6998. +    if(vif->flags&VIFF_TUNNEL)
  6999. +    {
  7000. +        tunnel=16;
  7001. +        raddr=vif->remote;
  7002. +    }
  7003. +    vif->pkt_out++;
  7004. +    vif->bytes_out+=skb->len;
  7005. +    skb->dev=vif->dev;
  7006. +    skb->raddr=skb->h.iph->daddr;
  7007. +    if(ip_forward(skb, in_dev, frag|8|tunnel, raddr)==-1)
  7008. +        kfree_skb(skb, FREE_WRITE);
  7009. +}
  7010. +
  7011. +/*
  7012. + *    Multicast packets for forwarding arrive here
  7013. + */
  7014. +
  7015. +void ipmr_forward(struct sk_buff *skb, int is_frag)
  7016. +{
  7017. +    struct mfc_cache *cache;
  7018. +    struct sk_buff *skb2;
  7019. +    int psend = -1;
  7020. +    int vif=ipmr_vifi_find(skb->dev);
  7021. +    if(vif==-1)
  7022. +    {
  7023. +        kfree_skb(skb, FREE_WRITE);
  7024. +        return;
  7025. +    }
  7026. +    
  7027. +    vif_table[vif].pkt_in++;
  7028. +    vif_table[vif].bytes_in+=skb->len;
  7029.      
  7030. +    cache=ipmr_cache_find(skb->ip_hdr->saddr,skb->ip_hdr->daddr);
  7031. +    
  7032. +    /*
  7033. +     *    No usable cache entry
  7034. +     */
  7035. +     
  7036. +    if(cache==NULL || (cache->mfc_flags&MFC_QUEUED))
  7037. +        ipmr_cache_unresolved(cache,vif,skb, is_frag);
  7038. +    else
  7039. +    {
  7040. +        /*
  7041. +         *    Forward the frame
  7042. +         */
  7043. +         int ct=0;
  7044. +         while(ct<MAXVIFS)
  7045. +         {
  7046. +             /*
  7047. +              *    0 means don't do it. Silly idea, 255 as don't do it would be cleaner!
  7048. +              */
  7049. +             if(skb->ip_hdr->ttl > cache->mfc_ttls[ct] && cache->mfc_ttls[ct]>0)
  7050. +             {
  7051. +                 if(psend!=-1)
  7052. +                 {
  7053. +                     skb2=skb_clone(skb, GFP_ATOMIC);
  7054. +                     if(skb2)
  7055. +                     {
  7056. +                         skb2->free=1;
  7057. +                         ipmr_queue_xmit(skb2, &vif_table[psend], skb->dev, is_frag);
  7058. +                     }
  7059. +                }
  7060. +                psend=ct;
  7061. +            }
  7062. +            ct++;
  7063. +        }
  7064. +        if(psend==-1)
  7065. +            kfree_skb(skb, FREE_WRITE);
  7066. +        else
  7067. +        {
  7068. +            ipmr_queue_xmit(skb, &vif_table[psend], skb->dev, is_frag);
  7069. +        }
  7070. +        /*
  7071. +         *    Adjust the stats
  7072. +         */
  7073. +    }
  7074. +}
  7075.  
  7076. +/*
  7077. + *    The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
  7078. + */
  7079. +int ipmr_vif_info(char *buffer, char **start, off_t offset, int length, int dummy)
  7080. +{
  7081. +    struct vif_device *vif;
  7082. +    int len=0;
  7083. +    off_t pos=0;
  7084. +    off_t begin=0;
  7085. +    int size;
  7086. +    int ct;
  7087. +
  7088. +    len += sprintf(buffer,
  7089. +         "Interface  Bytes In  Pkts In  Bytes Out  Pkts Out  Flags Local    Remote\n");
  7090. +    pos=len;
  7091. +  
  7092. +    for (ct=0;ct<MAXVIFS;ct++) 
  7093. +    {
  7094. +        vif=&vif_table[ct];
  7095. +        if(!(vifc_map&(1<<ct)))
  7096. +            continue;
  7097. +        if(vif->dev==NULL)
  7098. +            continue;
  7099. +            size = sprintf(buffer+len, "%-10s %8ld  %7ld  %8ld   %7ld   %05X %08lX %08lX\n",
  7100. +                vif->dev->name,vif->bytes_in, vif->pkt_in, vif->bytes_out,vif->pkt_out,
  7101. +                vif->flags, vif->local, vif->remote);
  7102. +        len+=size;
  7103. +        pos+=size;
  7104. +        if(pos<offset)
  7105. +        {
  7106. +            len=0;
  7107. +            begin=pos;
  7108. +        }
  7109. +        if(pos>offset+length)
  7110. +            break;
  7111. +      }
  7112. +      
  7113. +      *start=buffer+(offset-begin);
  7114. +      len-=(offset-begin);
  7115. +      if(len>length)
  7116. +          len=length;
  7117. +      return len;
  7118. +}
  7119. +
  7120. +int ipmr_mfc_info(char *buffer, char **start, off_t offset, int length, int dummy)
  7121. +{
  7122. +    struct mfc_cache *mfc;
  7123. +    int len=0;
  7124. +    off_t pos=0;
  7125. +    off_t begin=0;
  7126. +    int size;
  7127. +    int ct;
  7128. +
  7129. +    len += sprintf(buffer,
  7130. +         "Group    Origin   SrcIface \n");
  7131. +    pos=len;
  7132. +  
  7133. +    for (ct=0;ct<MFC_LINES;ct++) 
  7134. +    {
  7135. +        cli();
  7136. +        mfc=mfc_cache_array[ct];
  7137. +        while(mfc!=NULL)
  7138. +        {
  7139. +            char *name="none";
  7140. +            char vifmap[MAXVIFS+1];
  7141. +            int n;
  7142. +            /*
  7143. +             *    Device name
  7144. +             */
  7145. +            if(vifc_map&(1<<mfc->mfc_parent))
  7146. +                name=vif_table[mfc->mfc_parent].dev->name;
  7147. +            /*
  7148. +             *    Interface forwarding map
  7149. +             */
  7150. +            for(n=0;n<MAXVIFS;n++)
  7151. +                if(vifc_map&(1<<n) && mfc->mfc_ttls[ct])
  7152. +                    vifmap[n]='X';
  7153. +                else
  7154. +                    vifmap[n]='-';
  7155. +            vifmap[n]=0;
  7156. +            /*
  7157. +             *    Now print it out
  7158. +             */
  7159. +            size = sprintf(buffer+len, "%08lX %08lX %-8s %s\n",
  7160. +                (unsigned long)mfc->mfc_mcastgrp,
  7161. +                (unsigned long)mfc->mfc_origin,
  7162. +                name,
  7163. +                vifmap);
  7164. +            len+=size;
  7165. +            pos+=size;
  7166. +            if(pos<offset)
  7167. +            {
  7168. +                len=0;
  7169. +                begin=pos;
  7170. +            }
  7171. +            if(pos>offset+length)
  7172. +            {
  7173. +                sti();
  7174. +                goto done;
  7175. +            }
  7176. +            mfc=mfc->next;
  7177. +          }
  7178. +          sti();
  7179. +      }
  7180. +done:
  7181. +      *start=buffer+(offset-begin);
  7182. +      len-=(offset-begin);
  7183. +      if(len>length)
  7184. +          len=length;
  7185. +      return len;
  7186. +}
  7187. +
  7188. +/*
  7189. + *    Setup for IP multicast routing
  7190. + */
  7191.  void ip_mr_init(void)
  7192.  {
  7193. -    printk("Linux IP multicast router 0.00pre-working 8)\n");
  7194. +    printk("Linux IP multicast router 0.02pre-working 8)\n");
  7195.      register_netdevice_notifier(&ip_mr_notifier);
  7196. +    proc_net_register(&(struct proc_dir_entry) {
  7197. +        PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
  7198. +        S_IFREG | S_IRUGO, 1, 0, 0,
  7199. +        0, &proc_net_inode_operations,
  7200. +        ipmr_vif_info
  7201. +    });
  7202. +    proc_net_register(&(struct proc_dir_entry) {
  7203. +        PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
  7204. +        S_IFREG | S_IRUGO, 1, 0, 0,
  7205. +        0, &proc_net_inode_operations,
  7206. +        ipmr_mfc_info
  7207. +    });
  7208.  }
  7209.  
  7210.  #endif
  7211. diff -u --recursive --new-file v1.3.30/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
  7212. --- v1.3.30/linux/net/ipv4/tcp.c    Wed Sep 27 16:00:02 1995
  7213. +++ linux/net/ipv4/tcp.c    Mon Oct  2 14:25:13 1995
  7214. @@ -509,6 +509,8 @@
  7215.      sk->state=state;
  7216.      if(state==TCP_ESTABLISHED)
  7217.          tcp_statistics.TcpCurrEstab++;
  7218. +    if(sk->state==TCP_CLOSE)
  7219. +        tcp_cache_zap();
  7220.  }
  7221.  
  7222.  /*
  7223. diff -u --recursive --new-file v1.3.30/linux/net/netlink.c linux/net/netlink.c
  7224. --- v1.3.30/linux/net/netlink.c    Thu Jan  1 02:00:00 1970
  7225. +++ linux/net/netlink.c    Mon Oct  2 14:25:13 1995
  7226. @@ -0,0 +1,250 @@
  7227. +/*
  7228. + * SKIPLINK    An implementation of a loadable kernel mode driver providing
  7229. + *        multiple kernel/user space bidirectional communications links.
  7230. + *
  7231. + *         Author:     Alan Cox <alan@cymru.net>
  7232. + *
  7233. + *        This program is free software; you can redistribute it and/or
  7234. + *        modify it under the terms of the GNU General Public License
  7235. + *        as published by the Free Software Foundation; either version
  7236. + *        2 of the License, or (at your option) any later version.
  7237. + * 
  7238. + */
  7239. +
  7240. +#include <linux/config.h>
  7241. +
  7242. +#if defined(CONFIG_NETLINK) || defined(MODULE)
  7243. +#ifdef MODULE
  7244. +#include <linux/module.h>
  7245. +#include <linux/version.h>
  7246. +#else
  7247. +#define MOD_INC_USE_COUNT
  7248. +#define MOD_DEC_USE_COUNT
  7249. +#endif
  7250. +
  7251. +#include <linux/errno.h>
  7252. +#include <linux/kernel.h>
  7253. +#include <linux/major.h>
  7254. +#include <linux/sched.h>
  7255. +#include <linux/lp.h>
  7256. +#include <linux/malloc.h>
  7257. +#include <linux/ioport.h>
  7258. +#include <linux/fcntl.h>
  7259. +#include <linux/delay.h>
  7260. +#include <linux/skbuff.h>
  7261. +
  7262. +#include <net/netlink.h>
  7263. +
  7264. +#include <asm/io.h>
  7265. +#include <asm/segment.h>
  7266. +#include <asm/system.h>
  7267. +
  7268. +static int (*netlink_handler[MAX_LINKS])(struct sk_buff *skb);
  7269. +static struct sk_buff_head skb_queue_rd[MAX_LINKS]; 
  7270. +static int rdq_size[MAX_LINKS];
  7271. +static struct wait_queue *read_space_wait[MAX_LINKS];
  7272. +
  7273. +static int active_map = 0;
  7274. +static int open_map = 0;
  7275. +
  7276. +/*
  7277. + *    Device operations
  7278. + */
  7279. +/*
  7280. + *    Default write handler.
  7281. + */
  7282. +static int netlink_err(struct sk_buff *skb)
  7283. +{
  7284. +    kfree_skb(skb, FREE_READ);
  7285. +    return -EUNATCH;
  7286. +}
  7287. +/*
  7288. + *    Write a message to the kernel side of a communication link
  7289. + */
  7290. +static int netlink_write(struct inode * inode, struct file * file, const char * buf, int count)
  7291. +{
  7292. +    unsigned int minor = MINOR(inode->i_rdev);
  7293. +    struct sk_buff *skb;
  7294. +    skb=alloc_skb(count, GFP_KERNEL);
  7295. +    memcpy_fromfs(skb_put(skb,count),buf, count);
  7296. +    return (netlink_handler[minor])(skb);
  7297. +}
  7298. +
  7299. +/*
  7300. + *    Read a message from the kernel side of the communication link
  7301. + */
  7302. +
  7303. +static int netlink_read(struct inode * inode, struct file * file, char * buf, int count)
  7304. +{
  7305. +    unsigned int minor = MINOR(inode->i_rdev);
  7306. +    struct sk_buff *skb;
  7307. +    cli();
  7308. +    while((skb=skb_dequeue(&skb_queue_rd[minor]))==NULL)
  7309. +    {
  7310. +        if(file->f_flags&O_NONBLOCK)
  7311. +        {
  7312. +            sti();
  7313. +            return -EWOULDBLOCK;
  7314. +        }
  7315. +        interruptible_sleep_on(&read_space_wait[minor]);
  7316. +        if(current->signal & ~current->blocked)
  7317. +        {
  7318. +            sti();
  7319. +            return -ERESTARTSYS;
  7320. +        }
  7321. +    }
  7322. +    rdq_size[minor]-=skb->len;
  7323. +    sti();
  7324. +    if(skb->len<count)
  7325. +        count=skb->len;
  7326. +    memcpy_tofs(buf,skb->data,count);
  7327. +    kfree_skb(skb, FREE_READ);
  7328. +    return count;
  7329. +}
  7330. +
  7331. +static int netlink_lseek(struct inode * inode, struct file * file,
  7332. +            off_t offset, int origin)
  7333. +{
  7334. +    return -ESPIPE;
  7335. +}
  7336. +
  7337. +static int netlink_open(struct inode * inode, struct file * file)
  7338. +{
  7339. +    unsigned int minor = MINOR(inode->i_rdev);
  7340. +    
  7341. +    if(minor>=MAX_LINKS)
  7342. +        return -ENODEV;
  7343. +    if(open_map&(1<<minor))
  7344. +        return -EBUSY;
  7345. +    if(active_map&(1<<minor))
  7346. +    {
  7347. +        open_map|=(1<<minor);
  7348. +        return 0;
  7349. +    }
  7350. +    return -EUNATCH;
  7351. +}
  7352. +
  7353. +static void netlink_release(struct inode * inode, struct file * file)
  7354. +{
  7355. +    unsigned int minor = MINOR(inode->i_rdev);
  7356. +    open_map&=~(1<<minor);    
  7357. +    MOD_DEC_USE_COUNT;
  7358. +}
  7359. +
  7360. +
  7361. +static int netlink_ioctl(struct inode *inode, struct file *file,
  7362. +            unsigned int cmd, unsigned long arg)
  7363. +{
  7364. +    unsigned int minor = MINOR(inode->i_rdev);
  7365. +    int retval = 0;
  7366. +
  7367. +    if (minor >= MAX_LINKS)
  7368. +        return -ENODEV;
  7369. +    switch ( cmd ) {
  7370. +        default:
  7371. +            retval = -EINVAL;
  7372. +    }
  7373. +    return retval;
  7374. +}
  7375. +
  7376. +
  7377. +static struct file_operations netlink_fops = {
  7378. +    netlink_lseek,
  7379. +    netlink_read,
  7380. +    netlink_write,
  7381. +    NULL,        /* netlink_readdir */
  7382. +    NULL,        /* netlink_select */
  7383. +    netlink_ioctl,
  7384. +    NULL,        /* netlink_mmap */
  7385. +    netlink_open,
  7386. +    netlink_release
  7387. +};
  7388. +
  7389. +/*
  7390. + *    We export these functions to other modules. They provide a 
  7391. + *    complete set of kernel non-blocking support for message
  7392. + *    queueing.
  7393. + */
  7394. +int netlink_attach(int unit, int (*function)(struct sk_buff *skb))
  7395. +{
  7396. +    if(unit>=MAX_LINKS)
  7397. +        return -ENODEV;
  7398. +    if(active_map&(1<<unit))
  7399. +        return -EBUSY;
  7400. +    active_map|=(1<<unit);
  7401. +    netlink_handler[unit]=function;
  7402. +    return 0;
  7403. +}
  7404. +
  7405. +void netlink_detach(int unit)
  7406. +{
  7407. +    active_map&=~(1<<unit);
  7408. +    netlink_handler[unit]=netlink_err;
  7409. +}
  7410. +
  7411. +int netlink_post(int unit, struct sk_buff *skb)
  7412. +{
  7413. +    unsigned long flags;
  7414. +    int ret;
  7415. +    save_flags(flags);
  7416. +    cli();
  7417. +    if(rdq_size[unit]+skb->len>MAX_QBYTES)
  7418. +        ret=-EWOULDBLOCK;
  7419. +    else
  7420. +    {
  7421. +        skb_queue_tail(&skb_queue_rd[unit], skb);
  7422. +        rdq_size[unit]+=skb->len;
  7423. +        ret=0;
  7424. +        wake_up_interruptible(&read_space_wait[MAX_LINKS]);
  7425. +    }
  7426. +    restore_flags(flags);
  7427. +    return ret;
  7428. +}
  7429. +
  7430. +
  7431. +#ifdef MODULE
  7432. +char kernel_version[]=UTS_RELEASE;
  7433. +
  7434. +int init_module(void)
  7435. +{
  7436. +    int ct;
  7437. +    printk("Network Kernel/User communications module 0.01 ALPHA\n");
  7438. +    if (register_chrdev(NET_MAJOR,"netlink",&netlink_fops)) {
  7439. +        printk("netlink: unable to get major %d\n", NET_MAJOR);
  7440. +        return -EIO;
  7441. +    }
  7442. +    for(ct=0;ct<MAX_LINKS;ct++)
  7443. +    {
  7444. +        skb_queue_head_init(&skb_queue_rd[ct]);
  7445. +        netlink_handler[ct]=netlink_err;
  7446. +    }
  7447. +    return 0;
  7448. +}
  7449. +
  7450. +void cleanup_module(void)
  7451. +{
  7452. +    unregister_chrdev(NET_MAJOR,"netlink");
  7453. +}
  7454. +
  7455. +#else
  7456. +
  7457. +void init_netlink(void)
  7458. +{
  7459. +    int ct;
  7460. +    /* Keep quiet on booting, we don't want too many messages */
  7461. +    if(register_chrdev(NET_MAJOR,"netlink", &netlink_fops))
  7462. +        printk("netlink: unable to get major %d\n", NET_MAJOR);
  7463. +    for(ct=0;ct<MAX_LINKS;ct++)
  7464. +    {
  7465. +        skb_queue_head_init(&skb_queue_rd[ct]);
  7466. +        netlink_handler[ct]=netlink_err;
  7467. +    }
  7468. +}
  7469. +
  7470. +#endif
  7471. +#endif
  7472. diff -u --recursive --new-file v1.3.30/linux/net/socket.c linux/net/socket.c
  7473. --- v1.3.30/linux/net/socket.c    Wed Sep 13 12:45:36 1995
  7474. +++ linux/net/socket.c    Mon Oct  2 14:25:13 1995
  7475. @@ -64,6 +64,8 @@
  7476.  #include <linux/netdevice.h>
  7477.  #include <linux/proc_fs.h>
  7478.  
  7479. +#include <net/netlink.h>
  7480. +
  7481.  #include <asm/system.h>
  7482.  #include <asm/segment.h>
  7483.  
  7484. @@ -1285,13 +1287,21 @@
  7485.  {
  7486.      int i;
  7487.  
  7488. -    printk("Swansea University Computer Society NET3.031 Snap #1 for Linux 1.3.25\n");
  7489. +    printk("Swansea University Computer Society NET3.031 Snap #3 for Linux 1.3.30\n");
  7490.  
  7491.      /*
  7492.       *    Initialize all address (protocol) families. 
  7493.       */
  7494.       
  7495.      for (i = 0; i < NPROTO; ++i) pops[i] = NULL;
  7496. +    
  7497. +    /*
  7498. +     *    The netlink device handler may be needed early.
  7499. +     */
  7500. +
  7501. +#ifdef CONFIG_NETLINK
  7502. +    init_netlink();
  7503. +#endif         
  7504.  
  7505.      /*
  7506.       *    Initialize the protocols module. 
  7507.