* swap modules
@ 2003-06-23 15:04 David Chow
2003-06-23 15:51 ` (corrected) " David Chow
0 siblings, 1 reply; 2+ messages in thread
From: David Chow @ 2003-06-23 15:04 UTC (permalink / raw)
To: linux-mm
[-- Attachment #1: Type: text/plain, Size: 959 bytes --]
Dear linux-mm team,
This patch is for patching the mm and fs stuff to make the Linux 2.4.21
swap code to allow a concept of modularized swap methods. This concept
and swap code is originally from Justus Heine who created the NFS swap
patch for 2.2 and 2.4 . I've extracted the code and modified to make it
as a generic swap module code. The vanilla kernel swap code is been
moved to a file fs/blkdev_swap.c which is for normal plain block device
swaps. Users can configure the kernel to include the local block device
swap code or compile it as a module. Developers can also develop their
own swap methods instead of using the plain swap code (may be some
crypto for security reasons) . I've been using this API to develop NFS
swap and netswap code for a year an more. This patch has been tested for
more than a year in a production environment on smp and non-smp (I think
it is quite stable though). Please find it useful.
regards,
David Chow
[-- Attachment #2: swap_module-2.4.21.diff --]
[-- Type: text/plain, Size: 97449 bytes --]
diff -uaNr linux-2.4.21/Documentation/Configure.help linux-2.4.21-1APTUS/Documentation/Configure.help
--- linux-2.4.21/Documentation/Configure.help 2003-06-22 18:34:45.000000000 +0800
+++ linux-2.4.21-1APTUS/Documentation/Configure.help 2003-06-22 19:57:04.000000000 +0800
@@ -12784,6 +12784,16 @@
If you are running Linux on an IBM iSeries system and you want to
read a CD drive owned by OS/400, say Y here.
+Swapping to block device and local filesystems
+CONFIG_BLOCKDEV_SWAP
+ Say yes to enable virtual memory swap to block devices. If you have
+ a local disk drive and wish to use swap say 'Y', otherwise say 'N'.
+
+ If local swaping is option to your system, say 'M' and compile it
+ as a module.
+
+ If unsure, choose 'M' to compile it as a module for safe.
+
Quota support
CONFIG_QUOTA
If you say Y here, you will be able to set per user limits for disk
diff -uaNr linux-2.4.21/drivers/scsi/sim710_d.h linux-2.4.21-1APTUS/drivers/scsi/sim710_d.h
--- linux-2.4.21/drivers/scsi/sim710_d.h 1999-12-09 07:17:55.000000000 +0800
+++ linux-2.4.21-1APTUS/drivers/scsi/sim710_d.h 2003-06-23 02:19:11.000000000 +0800
@@ -18,15 +18,12 @@
ABSOLUTE reselected_identify = 0
ABSOLUTE msgin_buf = 0
+ABSOLUTE msg_reject = 0
+ABSOLUTE test1_src = 0
+ABSOLUTE test1_dst = 0
-ABSOLUTE int_bad_extmsg1a = 0xab930000
-ABSOLUTE int_bad_extmsg1b = 0xab930001
-ABSOLUTE int_bad_extmsg2a = 0xab930002
-ABSOLUTE int_bad_extmsg2b = 0xab930003
-ABSOLUTE int_bad_extmsg3a = 0xab930004
-ABSOLUTE int_bad_extmsg3b = 0xab930005
ABSOLUTE int_bad_msg1 = 0xab930006
ABSOLUTE int_bad_msg2 = 0xab930007
ABSOLUTE int_bad_msg3 = 0xab930008
@@ -50,7 +47,7 @@
ABSOLUTE int_disc2 = 0xab93001a
ABSOLUTE int_disc3 = 0xab93001b
ABSOLUTE int_not_rej = 0xab93001c
-
+ABSOLUTE int_test1 = 0xab93001d
@@ -65,6 +62,9 @@
+ABSOLUTE did_reject = 0x01
+
+
@@ -74,1641 +74,1709 @@
at 0x00000000 : */ 0x60000200,0x00000000,
/*
- MOVE SCRATCH0 & 0 TO SCRATCH0
-
-at 0x00000002 : */ 0x7c340000,0x00000000,
-/*
; Enable selection timer
MOVE CTEST7 & 0xef TO CTEST7
-at 0x00000004 : */ 0x7c1bef00,0x00000000,
+at 0x00000002 : */ 0x7c1bef00,0x00000000,
/*
SELECT ATN FROM dsa_select, reselect
-at 0x00000006 : */ 0x43000000,0x00000c48,
+at 0x00000004 : */ 0x43000000,0x00000cd0,
/*
JUMP get_status, WHEN STATUS
-at 0x00000008 : */ 0x830b0000,0x000000a0,
+at 0x00000006 : */ 0x830b0000,0x00000098,
/*
; Disable selection timer
MOVE CTEST7 | 0x10 TO CTEST7
-at 0x0000000a : */ 0x7a1b1000,0x00000000,
+at 0x00000008 : */ 0x7a1b1000,0x00000000,
/*
MOVE SCRATCH0 | had_select TO SCRATCH0
-at 0x0000000c : */ 0x7a340100,0x00000000,
+at 0x0000000a : */ 0x7a340100,0x00000000,
/*
INT int_sel_no_ident, IF NOT MSG_OUT
-at 0x0000000e : */ 0x9e020000,0xab930013,
+at 0x0000000c : */ 0x9e020000,0xab930013,
/*
MOVE SCRATCH0 | had_msgout TO SCRATCH0
-at 0x00000010 : */ 0x7a340200,0x00000000,
+at 0x0000000e : */ 0x7a340200,0x00000000,
/*
MOVE FROM dsa_msgout, when MSG_OUT
-at 0x00000012 : */ 0x1e000000,0x00000008,
+at 0x00000010 : */ 0x1e000000,0x00000008,
/*
ENTRY done_ident
done_ident:
JUMP get_status, IF STATUS
-at 0x00000014 : */ 0x830a0000,0x000000a0,
+at 0x00000012 : */ 0x830a0000,0x00000098,
/*
redo_msgin1:
JUMP get_msgin1, WHEN MSG_IN
-at 0x00000016 : */ 0x870b0000,0x00000920,
+at 0x00000014 : */ 0x870b0000,0x00000918,
/*
INT int_sel_not_cmd, IF NOT CMD
-at 0x00000018 : */ 0x9a020000,0xab930014,
+at 0x00000016 : */ 0x9a020000,0xab930014,
/*
ENTRY resume_cmd
resume_cmd:
MOVE SCRATCH0 | had_cmdout TO SCRATCH0
-at 0x0000001a : */ 0x7a340400,0x00000000,
+at 0x00000018 : */ 0x7a340400,0x00000000,
/*
MOVE FROM dsa_cmnd, WHEN CMD
-at 0x0000001c : */ 0x1a000000,0x00000010,
+at 0x0000001a : */ 0x1a000000,0x00000010,
/*
ENTRY resume_pmm
resume_pmm:
redo_msgin2:
JUMP get_msgin2, WHEN MSG_IN
-at 0x0000001e : */ 0x870b0000,0x00000a20,
+at 0x0000001c : */ 0x870b0000,0x00000a48,
/*
JUMP get_status, IF STATUS
-at 0x00000020 : */ 0x830a0000,0x000000a0,
+at 0x0000001e : */ 0x830a0000,0x00000098,
/*
JUMP input_data, IF DATA_IN
-at 0x00000022 : */ 0x810a0000,0x000000e0,
+at 0x00000020 : */ 0x810a0000,0x000000d8,
/*
JUMP output_data, IF DATA_OUT
-at 0x00000024 : */ 0x800a0000,0x000004f8,
+at 0x00000022 : */ 0x800a0000,0x000004f0,
/*
INT int_cmd_bad_phase
-at 0x00000026 : */ 0x98080000,0xab930009,
+at 0x00000024 : */ 0x98080000,0xab930009,
/*
get_status:
; Disable selection timer
MOVE CTEST7 | 0x10 TO CTEST7
-at 0x00000028 : */ 0x7a1b1000,0x00000000,
+at 0x00000026 : */ 0x7a1b1000,0x00000000,
/*
MOVE FROM dsa_status, WHEN STATUS
-at 0x0000002a : */ 0x1b000000,0x00000018,
+at 0x00000028 : */ 0x1b000000,0x00000018,
/*
INT int_status_not_msgin, WHEN NOT MSG_IN
-at 0x0000002c : */ 0x9f030000,0xab930015,
+at 0x0000002a : */ 0x9f030000,0xab930015,
/*
MOVE FROM dsa_msgin, WHEN MSG_IN
-at 0x0000002e : */ 0x1f000000,0x00000020,
+at 0x0000002c : */ 0x1f000000,0x00000020,
/*
INT int_not_cmd_complete, IF NOT 0x00
-at 0x00000030 : */ 0x98040000,0xab930012,
+at 0x0000002e : */ 0x98040000,0xab930012,
/*
CLEAR ACK
-at 0x00000032 : */ 0x60000040,0x00000000,
+at 0x00000030 : */ 0x60000040,0x00000000,
/*
ENTRY wait_disc_complete
wait_disc_complete:
WAIT DISCONNECT
-at 0x00000034 : */ 0x48000000,0x00000000,
+at 0x00000032 : */ 0x48000000,0x00000000,
/*
INT int_cmd_complete
-at 0x00000036 : */ 0x98080000,0xab93000a,
+at 0x00000034 : */ 0x98080000,0xab93000a,
/*
input_data:
MOVE SCRATCH0 | had_datain TO SCRATCH0
-at 0x00000038 : */ 0x7a340800,0x00000000,
+at 0x00000036 : */ 0x7a340800,0x00000000,
/*
ENTRY patch_input_data
patch_input_data:
JUMP 0
-at 0x0000003a : */ 0x80080000,0x00000000,
+at 0x00000038 : */ 0x80080000,0x00000000,
/*
MOVE FROM dsa_datain+0x0000, WHEN DATA_IN
-at 0x0000003c : */ 0x19000000,0x00000028,
+at 0x0000003a : */ 0x19000000,0x00000028,
/*
MOVE FROM dsa_datain+0x0008, WHEN DATA_IN
-at 0x0000003e : */ 0x19000000,0x00000030,
+at 0x0000003c : */ 0x19000000,0x00000030,
/*
MOVE FROM dsa_datain+0x0010, WHEN DATA_IN
-at 0x00000040 : */ 0x19000000,0x00000038,
+at 0x0000003e : */ 0x19000000,0x00000038,
/*
MOVE FROM dsa_datain+0x0018, WHEN DATA_IN
-at 0x00000042 : */ 0x19000000,0x00000040,
+at 0x00000040 : */ 0x19000000,0x00000040,
/*
MOVE FROM dsa_datain+0x0020, WHEN DATA_IN
-at 0x00000044 : */ 0x19000000,0x00000048,
+at 0x00000042 : */ 0x19000000,0x00000048,
/*
MOVE FROM dsa_datain+0x0028, WHEN DATA_IN
-at 0x00000046 : */ 0x19000000,0x00000050,
+at 0x00000044 : */ 0x19000000,0x00000050,
/*
MOVE FROM dsa_datain+0x0030, WHEN DATA_IN
-at 0x00000048 : */ 0x19000000,0x00000058,
+at 0x00000046 : */ 0x19000000,0x00000058,
/*
MOVE FROM dsa_datain+0x0038, WHEN DATA_IN
-at 0x0000004a : */ 0x19000000,0x00000060,
+at 0x00000048 : */ 0x19000000,0x00000060,
/*
MOVE FROM dsa_datain+0x0040, WHEN DATA_IN
-at 0x0000004c : */ 0x19000000,0x00000068,
+at 0x0000004a : */ 0x19000000,0x00000068,
/*
MOVE FROM dsa_datain+0x0048, WHEN DATA_IN
-at 0x0000004e : */ 0x19000000,0x00000070,
+at 0x0000004c : */ 0x19000000,0x00000070,
/*
MOVE FROM dsa_datain+0x0050, WHEN DATA_IN
-at 0x00000050 : */ 0x19000000,0x00000078,
+at 0x0000004e : */ 0x19000000,0x00000078,
/*
MOVE FROM dsa_datain+0x0058, WHEN DATA_IN
-at 0x00000052 : */ 0x19000000,0x00000080,
+at 0x00000050 : */ 0x19000000,0x00000080,
/*
MOVE FROM dsa_datain+0x0060, WHEN DATA_IN
-at 0x00000054 : */ 0x19000000,0x00000088,
+at 0x00000052 : */ 0x19000000,0x00000088,
/*
MOVE FROM dsa_datain+0x0068, WHEN DATA_IN
-at 0x00000056 : */ 0x19000000,0x00000090,
+at 0x00000054 : */ 0x19000000,0x00000090,
/*
MOVE FROM dsa_datain+0x0070, WHEN DATA_IN
-at 0x00000058 : */ 0x19000000,0x00000098,
+at 0x00000056 : */ 0x19000000,0x00000098,
/*
MOVE FROM dsa_datain+0x0078, WHEN DATA_IN
-at 0x0000005a : */ 0x19000000,0x000000a0,
+at 0x00000058 : */ 0x19000000,0x000000a0,
/*
MOVE FROM dsa_datain+0x0080, WHEN DATA_IN
-at 0x0000005c : */ 0x19000000,0x000000a8,
+at 0x0000005a : */ 0x19000000,0x000000a8,
/*
MOVE FROM dsa_datain+0x0088, WHEN DATA_IN
-at 0x0000005e : */ 0x19000000,0x000000b0,
+at 0x0000005c : */ 0x19000000,0x000000b0,
/*
MOVE FROM dsa_datain+0x0090, WHEN DATA_IN
-at 0x00000060 : */ 0x19000000,0x000000b8,
+at 0x0000005e : */ 0x19000000,0x000000b8,
/*
MOVE FROM dsa_datain+0x0098, WHEN DATA_IN
-at 0x00000062 : */ 0x19000000,0x000000c0,
+at 0x00000060 : */ 0x19000000,0x000000c0,
/*
MOVE FROM dsa_datain+0x00a0, WHEN DATA_IN
-at 0x00000064 : */ 0x19000000,0x000000c8,
+at 0x00000062 : */ 0x19000000,0x000000c8,
/*
MOVE FROM dsa_datain+0x00a8, WHEN DATA_IN
-at 0x00000066 : */ 0x19000000,0x000000d0,
+at 0x00000064 : */ 0x19000000,0x000000d0,
/*
MOVE FROM dsa_datain+0x00b0, WHEN DATA_IN
-at 0x00000068 : */ 0x19000000,0x000000d8,
+at 0x00000066 : */ 0x19000000,0x000000d8,
/*
MOVE FROM dsa_datain+0x00b8, WHEN DATA_IN
-at 0x0000006a : */ 0x19000000,0x000000e0,
+at 0x00000068 : */ 0x19000000,0x000000e0,
/*
MOVE FROM dsa_datain+0x00c0, WHEN DATA_IN
-at 0x0000006c : */ 0x19000000,0x000000e8,
+at 0x0000006a : */ 0x19000000,0x000000e8,
/*
MOVE FROM dsa_datain+0x00c8, WHEN DATA_IN
-at 0x0000006e : */ 0x19000000,0x000000f0,
+at 0x0000006c : */ 0x19000000,0x000000f0,
/*
MOVE FROM dsa_datain+0x00d0, WHEN DATA_IN
-at 0x00000070 : */ 0x19000000,0x000000f8,
+at 0x0000006e : */ 0x19000000,0x000000f8,
/*
MOVE FROM dsa_datain+0x00d8, WHEN DATA_IN
-at 0x00000072 : */ 0x19000000,0x00000100,
+at 0x00000070 : */ 0x19000000,0x00000100,
/*
MOVE FROM dsa_datain+0x00e0, WHEN DATA_IN
-at 0x00000074 : */ 0x19000000,0x00000108,
+at 0x00000072 : */ 0x19000000,0x00000108,
/*
MOVE FROM dsa_datain+0x00e8, WHEN DATA_IN
-at 0x00000076 : */ 0x19000000,0x00000110,
+at 0x00000074 : */ 0x19000000,0x00000110,
/*
MOVE FROM dsa_datain+0x00f0, WHEN DATA_IN
-at 0x00000078 : */ 0x19000000,0x00000118,
+at 0x00000076 : */ 0x19000000,0x00000118,
/*
MOVE FROM dsa_datain+0x00f8, WHEN DATA_IN
-at 0x0000007a : */ 0x19000000,0x00000120,
+at 0x00000078 : */ 0x19000000,0x00000120,
/*
MOVE FROM dsa_datain+0x0100, WHEN DATA_IN
-at 0x0000007c : */ 0x19000000,0x00000128,
+at 0x0000007a : */ 0x19000000,0x00000128,
/*
MOVE FROM dsa_datain+0x0108, WHEN DATA_IN
-at 0x0000007e : */ 0x19000000,0x00000130,
+at 0x0000007c : */ 0x19000000,0x00000130,
/*
MOVE FROM dsa_datain+0x0110, WHEN DATA_IN
-at 0x00000080 : */ 0x19000000,0x00000138,
+at 0x0000007e : */ 0x19000000,0x00000138,
/*
MOVE FROM dsa_datain+0x0118, WHEN DATA_IN
-at 0x00000082 : */ 0x19000000,0x00000140,
+at 0x00000080 : */ 0x19000000,0x00000140,
/*
MOVE FROM dsa_datain+0x0120, WHEN DATA_IN
-at 0x00000084 : */ 0x19000000,0x00000148,
+at 0x00000082 : */ 0x19000000,0x00000148,
/*
MOVE FROM dsa_datain+0x0128, WHEN DATA_IN
-at 0x00000086 : */ 0x19000000,0x00000150,
+at 0x00000084 : */ 0x19000000,0x00000150,
/*
MOVE FROM dsa_datain+0x0130, WHEN DATA_IN
-at 0x00000088 : */ 0x19000000,0x00000158,
+at 0x00000086 : */ 0x19000000,0x00000158,
/*
MOVE FROM dsa_datain+0x0138, WHEN DATA_IN
-at 0x0000008a : */ 0x19000000,0x00000160,
+at 0x00000088 : */ 0x19000000,0x00000160,
/*
MOVE FROM dsa_datain+0x0140, WHEN DATA_IN
-at 0x0000008c : */ 0x19000000,0x00000168,
+at 0x0000008a : */ 0x19000000,0x00000168,
/*
MOVE FROM dsa_datain+0x0148, WHEN DATA_IN
-at 0x0000008e : */ 0x19000000,0x00000170,
+at 0x0000008c : */ 0x19000000,0x00000170,
/*
MOVE FROM dsa_datain+0x0150, WHEN DATA_IN
-at 0x00000090 : */ 0x19000000,0x00000178,
+at 0x0000008e : */ 0x19000000,0x00000178,
/*
MOVE FROM dsa_datain+0x0158, WHEN DATA_IN
-at 0x00000092 : */ 0x19000000,0x00000180,
+at 0x00000090 : */ 0x19000000,0x00000180,
/*
MOVE FROM dsa_datain+0x0160, WHEN DATA_IN
-at 0x00000094 : */ 0x19000000,0x00000188,
+at 0x00000092 : */ 0x19000000,0x00000188,
/*
MOVE FROM dsa_datain+0x0168, WHEN DATA_IN
-at 0x00000096 : */ 0x19000000,0x00000190,
+at 0x00000094 : */ 0x19000000,0x00000190,
/*
MOVE FROM dsa_datain+0x0170, WHEN DATA_IN
-at 0x00000098 : */ 0x19000000,0x00000198,
+at 0x00000096 : */ 0x19000000,0x00000198,
/*
MOVE FROM dsa_datain+0x0178, WHEN DATA_IN
-at 0x0000009a : */ 0x19000000,0x000001a0,
+at 0x00000098 : */ 0x19000000,0x000001a0,
/*
MOVE FROM dsa_datain+0x0180, WHEN DATA_IN
-at 0x0000009c : */ 0x19000000,0x000001a8,
+at 0x0000009a : */ 0x19000000,0x000001a8,
/*
MOVE FROM dsa_datain+0x0188, WHEN DATA_IN
-at 0x0000009e : */ 0x19000000,0x000001b0,
+at 0x0000009c : */ 0x19000000,0x000001b0,
/*
MOVE FROM dsa_datain+0x0190, WHEN DATA_IN
-at 0x000000a0 : */ 0x19000000,0x000001b8,
+at 0x0000009e : */ 0x19000000,0x000001b8,
/*
MOVE FROM dsa_datain+0x0198, WHEN DATA_IN
-at 0x000000a2 : */ 0x19000000,0x000001c0,
+at 0x000000a0 : */ 0x19000000,0x000001c0,
/*
MOVE FROM dsa_datain+0x01a0, WHEN DATA_IN
-at 0x000000a4 : */ 0x19000000,0x000001c8,
+at 0x000000a2 : */ 0x19000000,0x000001c8,
/*
MOVE FROM dsa_datain+0x01a8, WHEN DATA_IN
-at 0x000000a6 : */ 0x19000000,0x000001d0,
+at 0x000000a4 : */ 0x19000000,0x000001d0,
/*
MOVE FROM dsa_datain+0x01b0, WHEN DATA_IN
-at 0x000000a8 : */ 0x19000000,0x000001d8,
+at 0x000000a6 : */ 0x19000000,0x000001d8,
/*
MOVE FROM dsa_datain+0x01b8, WHEN DATA_IN
-at 0x000000aa : */ 0x19000000,0x000001e0,
+at 0x000000a8 : */ 0x19000000,0x000001e0,
/*
MOVE FROM dsa_datain+0x01c0, WHEN DATA_IN
-at 0x000000ac : */ 0x19000000,0x000001e8,
+at 0x000000aa : */ 0x19000000,0x000001e8,
/*
MOVE FROM dsa_datain+0x01c8, WHEN DATA_IN
-at 0x000000ae : */ 0x19000000,0x000001f0,
+at 0x000000ac : */ 0x19000000,0x000001f0,
/*
MOVE FROM dsa_datain+0x01d0, WHEN DATA_IN
-at 0x000000b0 : */ 0x19000000,0x000001f8,
+at 0x000000ae : */ 0x19000000,0x000001f8,
/*
MOVE FROM dsa_datain+0x01d8, WHEN DATA_IN
-at 0x000000b2 : */ 0x19000000,0x00000200,
+at 0x000000b0 : */ 0x19000000,0x00000200,
/*
MOVE FROM dsa_datain+0x01e0, WHEN DATA_IN
-at 0x000000b4 : */ 0x19000000,0x00000208,
+at 0x000000b2 : */ 0x19000000,0x00000208,
/*
MOVE FROM dsa_datain+0x01e8, WHEN DATA_IN
-at 0x000000b6 : */ 0x19000000,0x00000210,
+at 0x000000b4 : */ 0x19000000,0x00000210,
/*
MOVE FROM dsa_datain+0x01f0, WHEN DATA_IN
-at 0x000000b8 : */ 0x19000000,0x00000218,
+at 0x000000b6 : */ 0x19000000,0x00000218,
/*
MOVE FROM dsa_datain+0x01f8, WHEN DATA_IN
-at 0x000000ba : */ 0x19000000,0x00000220,
+at 0x000000b8 : */ 0x19000000,0x00000220,
/*
MOVE FROM dsa_datain+0x0200, WHEN DATA_IN
-at 0x000000bc : */ 0x19000000,0x00000228,
+at 0x000000ba : */ 0x19000000,0x00000228,
/*
MOVE FROM dsa_datain+0x0208, WHEN DATA_IN
-at 0x000000be : */ 0x19000000,0x00000230,
+at 0x000000bc : */ 0x19000000,0x00000230,
/*
MOVE FROM dsa_datain+0x0210, WHEN DATA_IN
-at 0x000000c0 : */ 0x19000000,0x00000238,
+at 0x000000be : */ 0x19000000,0x00000238,
/*
MOVE FROM dsa_datain+0x0218, WHEN DATA_IN
-at 0x000000c2 : */ 0x19000000,0x00000240,
+at 0x000000c0 : */ 0x19000000,0x00000240,
/*
MOVE FROM dsa_datain+0x0220, WHEN DATA_IN
-at 0x000000c4 : */ 0x19000000,0x00000248,
+at 0x000000c2 : */ 0x19000000,0x00000248,
/*
MOVE FROM dsa_datain+0x0228, WHEN DATA_IN
-at 0x000000c6 : */ 0x19000000,0x00000250,
+at 0x000000c4 : */ 0x19000000,0x00000250,
/*
MOVE FROM dsa_datain+0x0230, WHEN DATA_IN
-at 0x000000c8 : */ 0x19000000,0x00000258,
+at 0x000000c6 : */ 0x19000000,0x00000258,
/*
MOVE FROM dsa_datain+0x0238, WHEN DATA_IN
-at 0x000000ca : */ 0x19000000,0x00000260,
+at 0x000000c8 : */ 0x19000000,0x00000260,
/*
MOVE FROM dsa_datain+0x0240, WHEN DATA_IN
-at 0x000000cc : */ 0x19000000,0x00000268,
+at 0x000000ca : */ 0x19000000,0x00000268,
/*
MOVE FROM dsa_datain+0x0248, WHEN DATA_IN
-at 0x000000ce : */ 0x19000000,0x00000270,
+at 0x000000cc : */ 0x19000000,0x00000270,
/*
MOVE FROM dsa_datain+0x0250, WHEN DATA_IN
-at 0x000000d0 : */ 0x19000000,0x00000278,
+at 0x000000ce : */ 0x19000000,0x00000278,
/*
MOVE FROM dsa_datain+0x0258, WHEN DATA_IN
-at 0x000000d2 : */ 0x19000000,0x00000280,
+at 0x000000d0 : */ 0x19000000,0x00000280,
/*
MOVE FROM dsa_datain+0x0260, WHEN DATA_IN
-at 0x000000d4 : */ 0x19000000,0x00000288,
+at 0x000000d2 : */ 0x19000000,0x00000288,
/*
MOVE FROM dsa_datain+0x0268, WHEN DATA_IN
-at 0x000000d6 : */ 0x19000000,0x00000290,
+at 0x000000d4 : */ 0x19000000,0x00000290,
/*
MOVE FROM dsa_datain+0x0270, WHEN DATA_IN
-at 0x000000d8 : */ 0x19000000,0x00000298,
+at 0x000000d6 : */ 0x19000000,0x00000298,
/*
MOVE FROM dsa_datain+0x0278, WHEN DATA_IN
-at 0x000000da : */ 0x19000000,0x000002a0,
+at 0x000000d8 : */ 0x19000000,0x000002a0,
/*
MOVE FROM dsa_datain+0x0280, WHEN DATA_IN
-at 0x000000dc : */ 0x19000000,0x000002a8,
+at 0x000000da : */ 0x19000000,0x000002a8,
/*
MOVE FROM dsa_datain+0x0288, WHEN DATA_IN
-at 0x000000de : */ 0x19000000,0x000002b0,
+at 0x000000dc : */ 0x19000000,0x000002b0,
/*
MOVE FROM dsa_datain+0x0290, WHEN DATA_IN
-at 0x000000e0 : */ 0x19000000,0x000002b8,
+at 0x000000de : */ 0x19000000,0x000002b8,
/*
MOVE FROM dsa_datain+0x0298, WHEN DATA_IN
-at 0x000000e2 : */ 0x19000000,0x000002c0,
+at 0x000000e0 : */ 0x19000000,0x000002c0,
/*
MOVE FROM dsa_datain+0x02a0, WHEN DATA_IN
-at 0x000000e4 : */ 0x19000000,0x000002c8,
+at 0x000000e2 : */ 0x19000000,0x000002c8,
/*
MOVE FROM dsa_datain+0x02a8, WHEN DATA_IN
-at 0x000000e6 : */ 0x19000000,0x000002d0,
+at 0x000000e4 : */ 0x19000000,0x000002d0,
/*
MOVE FROM dsa_datain+0x02b0, WHEN DATA_IN
-at 0x000000e8 : */ 0x19000000,0x000002d8,
+at 0x000000e6 : */ 0x19000000,0x000002d8,
/*
MOVE FROM dsa_datain+0x02b8, WHEN DATA_IN
-at 0x000000ea : */ 0x19000000,0x000002e0,
+at 0x000000e8 : */ 0x19000000,0x000002e0,
/*
MOVE FROM dsa_datain+0x02c0, WHEN DATA_IN
-at 0x000000ec : */ 0x19000000,0x000002e8,
+at 0x000000ea : */ 0x19000000,0x000002e8,
/*
MOVE FROM dsa_datain+0x02c8, WHEN DATA_IN
-at 0x000000ee : */ 0x19000000,0x000002f0,
+at 0x000000ec : */ 0x19000000,0x000002f0,
/*
MOVE FROM dsa_datain+0x02d0, WHEN DATA_IN
-at 0x000000f0 : */ 0x19000000,0x000002f8,
+at 0x000000ee : */ 0x19000000,0x000002f8,
/*
MOVE FROM dsa_datain+0x02d8, WHEN DATA_IN
-at 0x000000f2 : */ 0x19000000,0x00000300,
+at 0x000000f0 : */ 0x19000000,0x00000300,
/*
MOVE FROM dsa_datain+0x02e0, WHEN DATA_IN
-at 0x000000f4 : */ 0x19000000,0x00000308,
+at 0x000000f2 : */ 0x19000000,0x00000308,
/*
MOVE FROM dsa_datain+0x02e8, WHEN DATA_IN
-at 0x000000f6 : */ 0x19000000,0x00000310,
+at 0x000000f4 : */ 0x19000000,0x00000310,
/*
MOVE FROM dsa_datain+0x02f0, WHEN DATA_IN
-at 0x000000f8 : */ 0x19000000,0x00000318,
+at 0x000000f6 : */ 0x19000000,0x00000318,
/*
MOVE FROM dsa_datain+0x02f8, WHEN DATA_IN
-at 0x000000fa : */ 0x19000000,0x00000320,
+at 0x000000f8 : */ 0x19000000,0x00000320,
/*
MOVE FROM dsa_datain+0x0300, WHEN DATA_IN
-at 0x000000fc : */ 0x19000000,0x00000328,
+at 0x000000fa : */ 0x19000000,0x00000328,
/*
MOVE FROM dsa_datain+0x0308, WHEN DATA_IN
-at 0x000000fe : */ 0x19000000,0x00000330,
+at 0x000000fc : */ 0x19000000,0x00000330,
/*
MOVE FROM dsa_datain+0x0310, WHEN DATA_IN
-at 0x00000100 : */ 0x19000000,0x00000338,
+at 0x000000fe : */ 0x19000000,0x00000338,
/*
MOVE FROM dsa_datain+0x0318, WHEN DATA_IN
-at 0x00000102 : */ 0x19000000,0x00000340,
+at 0x00000100 : */ 0x19000000,0x00000340,
/*
MOVE FROM dsa_datain+0x0320, WHEN DATA_IN
-at 0x00000104 : */ 0x19000000,0x00000348,
+at 0x00000102 : */ 0x19000000,0x00000348,
/*
MOVE FROM dsa_datain+0x0328, WHEN DATA_IN
-at 0x00000106 : */ 0x19000000,0x00000350,
+at 0x00000104 : */ 0x19000000,0x00000350,
/*
MOVE FROM dsa_datain+0x0330, WHEN DATA_IN
-at 0x00000108 : */ 0x19000000,0x00000358,
+at 0x00000106 : */ 0x19000000,0x00000358,
/*
MOVE FROM dsa_datain+0x0338, WHEN DATA_IN
-at 0x0000010a : */ 0x19000000,0x00000360,
+at 0x00000108 : */ 0x19000000,0x00000360,
/*
MOVE FROM dsa_datain+0x0340, WHEN DATA_IN
-at 0x0000010c : */ 0x19000000,0x00000368,
+at 0x0000010a : */ 0x19000000,0x00000368,
/*
MOVE FROM dsa_datain+0x0348, WHEN DATA_IN
-at 0x0000010e : */ 0x19000000,0x00000370,
+at 0x0000010c : */ 0x19000000,0x00000370,
/*
MOVE FROM dsa_datain+0x0350, WHEN DATA_IN
-at 0x00000110 : */ 0x19000000,0x00000378,
+at 0x0000010e : */ 0x19000000,0x00000378,
/*
MOVE FROM dsa_datain+0x0358, WHEN DATA_IN
-at 0x00000112 : */ 0x19000000,0x00000380,
+at 0x00000110 : */ 0x19000000,0x00000380,
/*
MOVE FROM dsa_datain+0x0360, WHEN DATA_IN
-at 0x00000114 : */ 0x19000000,0x00000388,
+at 0x00000112 : */ 0x19000000,0x00000388,
/*
MOVE FROM dsa_datain+0x0368, WHEN DATA_IN
-at 0x00000116 : */ 0x19000000,0x00000390,
+at 0x00000114 : */ 0x19000000,0x00000390,
/*
MOVE FROM dsa_datain+0x0370, WHEN DATA_IN
-at 0x00000118 : */ 0x19000000,0x00000398,
+at 0x00000116 : */ 0x19000000,0x00000398,
/*
MOVE FROM dsa_datain+0x0378, WHEN DATA_IN
-at 0x0000011a : */ 0x19000000,0x000003a0,
+at 0x00000118 : */ 0x19000000,0x000003a0,
/*
MOVE FROM dsa_datain+0x0380, WHEN DATA_IN
-at 0x0000011c : */ 0x19000000,0x000003a8,
+at 0x0000011a : */ 0x19000000,0x000003a8,
/*
MOVE FROM dsa_datain+0x0388, WHEN DATA_IN
-at 0x0000011e : */ 0x19000000,0x000003b0,
+at 0x0000011c : */ 0x19000000,0x000003b0,
/*
MOVE FROM dsa_datain+0x0390, WHEN DATA_IN
-at 0x00000120 : */ 0x19000000,0x000003b8,
+at 0x0000011e : */ 0x19000000,0x000003b8,
/*
MOVE FROM dsa_datain+0x0398, WHEN DATA_IN
-at 0x00000122 : */ 0x19000000,0x000003c0,
+at 0x00000120 : */ 0x19000000,0x000003c0,
/*
MOVE FROM dsa_datain+0x03a0, WHEN DATA_IN
-at 0x00000124 : */ 0x19000000,0x000003c8,
+at 0x00000122 : */ 0x19000000,0x000003c8,
/*
MOVE FROM dsa_datain+0x03a8, WHEN DATA_IN
-at 0x00000126 : */ 0x19000000,0x000003d0,
+at 0x00000124 : */ 0x19000000,0x000003d0,
/*
MOVE FROM dsa_datain+0x03b0, WHEN DATA_IN
-at 0x00000128 : */ 0x19000000,0x000003d8,
+at 0x00000126 : */ 0x19000000,0x000003d8,
/*
MOVE FROM dsa_datain+0x03b8, WHEN DATA_IN
-at 0x0000012a : */ 0x19000000,0x000003e0,
+at 0x00000128 : */ 0x19000000,0x000003e0,
/*
MOVE FROM dsa_datain+0x03c0, WHEN DATA_IN
-at 0x0000012c : */ 0x19000000,0x000003e8,
+at 0x0000012a : */ 0x19000000,0x000003e8,
/*
MOVE FROM dsa_datain+0x03c8, WHEN DATA_IN
-at 0x0000012e : */ 0x19000000,0x000003f0,
+at 0x0000012c : */ 0x19000000,0x000003f0,
/*
MOVE FROM dsa_datain+0x03d0, WHEN DATA_IN
-at 0x00000130 : */ 0x19000000,0x000003f8,
+at 0x0000012e : */ 0x19000000,0x000003f8,
/*
MOVE FROM dsa_datain+0x03d8, WHEN DATA_IN
-at 0x00000132 : */ 0x19000000,0x00000400,
+at 0x00000130 : */ 0x19000000,0x00000400,
/*
MOVE FROM dsa_datain+0x03e0, WHEN DATA_IN
-at 0x00000134 : */ 0x19000000,0x00000408,
+at 0x00000132 : */ 0x19000000,0x00000408,
/*
MOVE FROM dsa_datain+0x03e8, WHEN DATA_IN
-at 0x00000136 : */ 0x19000000,0x00000410,
+at 0x00000134 : */ 0x19000000,0x00000410,
/*
MOVE FROM dsa_datain+0x03f0, WHEN DATA_IN
-at 0x00000138 : */ 0x19000000,0x00000418,
+at 0x00000136 : */ 0x19000000,0x00000418,
/*
MOVE FROM dsa_datain+0x03f8, WHEN DATA_IN
-at 0x0000013a : */ 0x19000000,0x00000420,
+at 0x00000138 : */ 0x19000000,0x00000420,
/*
JUMP end_data_trans
-at 0x0000013c : */ 0x80080000,0x00000908,
+at 0x0000013a : */ 0x80080000,0x00000900,
/*
output_data:
MOVE SCRATCH0 | had_dataout TO SCRATCH0
-at 0x0000013e : */ 0x7a341000,0x00000000,
+at 0x0000013c : */ 0x7a341000,0x00000000,
/*
ENTRY patch_output_data
patch_output_data:
JUMP 0
-at 0x00000140 : */ 0x80080000,0x00000000,
+at 0x0000013e : */ 0x80080000,0x00000000,
/*
MOVE FROM dsa_dataout+0x0000, WHEN DATA_OUT
-at 0x00000142 : */ 0x18000000,0x00000428,
+at 0x00000140 : */ 0x18000000,0x00000428,
/*
MOVE FROM dsa_dataout+0x0008, WHEN DATA_OUT
-at 0x00000144 : */ 0x18000000,0x00000430,
+at 0x00000142 : */ 0x18000000,0x00000430,
/*
MOVE FROM dsa_dataout+0x0010, WHEN DATA_OUT
-at 0x00000146 : */ 0x18000000,0x00000438,
+at 0x00000144 : */ 0x18000000,0x00000438,
/*
MOVE FROM dsa_dataout+0x0018, WHEN DATA_OUT
-at 0x00000148 : */ 0x18000000,0x00000440,
+at 0x00000146 : */ 0x18000000,0x00000440,
/*
MOVE FROM dsa_dataout+0x0020, WHEN DATA_OUT
-at 0x0000014a : */ 0x18000000,0x00000448,
+at 0x00000148 : */ 0x18000000,0x00000448,
/*
MOVE FROM dsa_dataout+0x0028, WHEN DATA_OUT
-at 0x0000014c : */ 0x18000000,0x00000450,
+at 0x0000014a : */ 0x18000000,0x00000450,
/*
MOVE FROM dsa_dataout+0x0030, WHEN DATA_OUT
-at 0x0000014e : */ 0x18000000,0x00000458,
+at 0x0000014c : */ 0x18000000,0x00000458,
/*
MOVE FROM dsa_dataout+0x0038, WHEN DATA_OUT
-at 0x00000150 : */ 0x18000000,0x00000460,
+at 0x0000014e : */ 0x18000000,0x00000460,
/*
MOVE FROM dsa_dataout+0x0040, WHEN DATA_OUT
-at 0x00000152 : */ 0x18000000,0x00000468,
+at 0x00000150 : */ 0x18000000,0x00000468,
/*
MOVE FROM dsa_dataout+0x0048, WHEN DATA_OUT
-at 0x00000154 : */ 0x18000000,0x00000470,
+at 0x00000152 : */ 0x18000000,0x00000470,
/*
MOVE FROM dsa_dataout+0x0050, WHEN DATA_OUT
-at 0x00000156 : */ 0x18000000,0x00000478,
+at 0x00000154 : */ 0x18000000,0x00000478,
/*
MOVE FROM dsa_dataout+0x0058, WHEN DATA_OUT
-at 0x00000158 : */ 0x18000000,0x00000480,
+at 0x00000156 : */ 0x18000000,0x00000480,
/*
MOVE FROM dsa_dataout+0x0060, WHEN DATA_OUT
-at 0x0000015a : */ 0x18000000,0x00000488,
+at 0x00000158 : */ 0x18000000,0x00000488,
/*
MOVE FROM dsa_dataout+0x0068, WHEN DATA_OUT
-at 0x0000015c : */ 0x18000000,0x00000490,
+at 0x0000015a : */ 0x18000000,0x00000490,
/*
MOVE FROM dsa_dataout+0x0070, WHEN DATA_OUT
-at 0x0000015e : */ 0x18000000,0x00000498,
+at 0x0000015c : */ 0x18000000,0x00000498,
/*
MOVE FROM dsa_dataout+0x0078, WHEN DATA_OUT
-at 0x00000160 : */ 0x18000000,0x000004a0,
+at 0x0000015e : */ 0x18000000,0x000004a0,
/*
MOVE FROM dsa_dataout+0x0080, WHEN DATA_OUT
-at 0x00000162 : */ 0x18000000,0x000004a8,
+at 0x00000160 : */ 0x18000000,0x000004a8,
/*
MOVE FROM dsa_dataout+0x0088, WHEN DATA_OUT
-at 0x00000164 : */ 0x18000000,0x000004b0,
+at 0x00000162 : */ 0x18000000,0x000004b0,
/*
MOVE FROM dsa_dataout+0x0090, WHEN DATA_OUT
-at 0x00000166 : */ 0x18000000,0x000004b8,
+at 0x00000164 : */ 0x18000000,0x000004b8,
/*
MOVE FROM dsa_dataout+0x0098, WHEN DATA_OUT
-at 0x00000168 : */ 0x18000000,0x000004c0,
+at 0x00000166 : */ 0x18000000,0x000004c0,
/*
MOVE FROM dsa_dataout+0x00a0, WHEN DATA_OUT
-at 0x0000016a : */ 0x18000000,0x000004c8,
+at 0x00000168 : */ 0x18000000,0x000004c8,
/*
MOVE FROM dsa_dataout+0x00a8, WHEN DATA_OUT
-at 0x0000016c : */ 0x18000000,0x000004d0,
+at 0x0000016a : */ 0x18000000,0x000004d0,
/*
MOVE FROM dsa_dataout+0x00b0, WHEN DATA_OUT
-at 0x0000016e : */ 0x18000000,0x000004d8,
+at 0x0000016c : */ 0x18000000,0x000004d8,
/*
MOVE FROM dsa_dataout+0x00b8, WHEN DATA_OUT
-at 0x00000170 : */ 0x18000000,0x000004e0,
+at 0x0000016e : */ 0x18000000,0x000004e0,
/*
MOVE FROM dsa_dataout+0x00c0, WHEN DATA_OUT
-at 0x00000172 : */ 0x18000000,0x000004e8,
+at 0x00000170 : */ 0x18000000,0x000004e8,
/*
MOVE FROM dsa_dataout+0x00c8, WHEN DATA_OUT
-at 0x00000174 : */ 0x18000000,0x000004f0,
+at 0x00000172 : */ 0x18000000,0x000004f0,
/*
MOVE FROM dsa_dataout+0x00d0, WHEN DATA_OUT
-at 0x00000176 : */ 0x18000000,0x000004f8,
+at 0x00000174 : */ 0x18000000,0x000004f8,
/*
MOVE FROM dsa_dataout+0x00d8, WHEN DATA_OUT
-at 0x00000178 : */ 0x18000000,0x00000500,
+at 0x00000176 : */ 0x18000000,0x00000500,
/*
MOVE FROM dsa_dataout+0x00e0, WHEN DATA_OUT
-at 0x0000017a : */ 0x18000000,0x00000508,
+at 0x00000178 : */ 0x18000000,0x00000508,
/*
MOVE FROM dsa_dataout+0x00e8, WHEN DATA_OUT
-at 0x0000017c : */ 0x18000000,0x00000510,
+at 0x0000017a : */ 0x18000000,0x00000510,
/*
MOVE FROM dsa_dataout+0x00f0, WHEN DATA_OUT
-at 0x0000017e : */ 0x18000000,0x00000518,
+at 0x0000017c : */ 0x18000000,0x00000518,
/*
MOVE FROM dsa_dataout+0x00f8, WHEN DATA_OUT
-at 0x00000180 : */ 0x18000000,0x00000520,
+at 0x0000017e : */ 0x18000000,0x00000520,
/*
MOVE FROM dsa_dataout+0x0100, WHEN DATA_OUT
-at 0x00000182 : */ 0x18000000,0x00000528,
+at 0x00000180 : */ 0x18000000,0x00000528,
/*
MOVE FROM dsa_dataout+0x0108, WHEN DATA_OUT
-at 0x00000184 : */ 0x18000000,0x00000530,
+at 0x00000182 : */ 0x18000000,0x00000530,
/*
MOVE FROM dsa_dataout+0x0110, WHEN DATA_OUT
-at 0x00000186 : */ 0x18000000,0x00000538,
+at 0x00000184 : */ 0x18000000,0x00000538,
/*
MOVE FROM dsa_dataout+0x0118, WHEN DATA_OUT
-at 0x00000188 : */ 0x18000000,0x00000540,
+at 0x00000186 : */ 0x18000000,0x00000540,
/*
MOVE FROM dsa_dataout+0x0120, WHEN DATA_OUT
-at 0x0000018a : */ 0x18000000,0x00000548,
+at 0x00000188 : */ 0x18000000,0x00000548,
/*
MOVE FROM dsa_dataout+0x0128, WHEN DATA_OUT
-at 0x0000018c : */ 0x18000000,0x00000550,
+at 0x0000018a : */ 0x18000000,0x00000550,
/*
MOVE FROM dsa_dataout+0x0130, WHEN DATA_OUT
-at 0x0000018e : */ 0x18000000,0x00000558,
+at 0x0000018c : */ 0x18000000,0x00000558,
/*
MOVE FROM dsa_dataout+0x0138, WHEN DATA_OUT
-at 0x00000190 : */ 0x18000000,0x00000560,
+at 0x0000018e : */ 0x18000000,0x00000560,
/*
MOVE FROM dsa_dataout+0x0140, WHEN DATA_OUT
-at 0x00000192 : */ 0x18000000,0x00000568,
+at 0x00000190 : */ 0x18000000,0x00000568,
/*
MOVE FROM dsa_dataout+0x0148, WHEN DATA_OUT
-at 0x00000194 : */ 0x18000000,0x00000570,
+at 0x00000192 : */ 0x18000000,0x00000570,
/*
MOVE FROM dsa_dataout+0x0150, WHEN DATA_OUT
-at 0x00000196 : */ 0x18000000,0x00000578,
+at 0x00000194 : */ 0x18000000,0x00000578,
/*
MOVE FROM dsa_dataout+0x0158, WHEN DATA_OUT
-at 0x00000198 : */ 0x18000000,0x00000580,
+at 0x00000196 : */ 0x18000000,0x00000580,
/*
MOVE FROM dsa_dataout+0x0160, WHEN DATA_OUT
-at 0x0000019a : */ 0x18000000,0x00000588,
+at 0x00000198 : */ 0x18000000,0x00000588,
/*
MOVE FROM dsa_dataout+0x0168, WHEN DATA_OUT
-at 0x0000019c : */ 0x18000000,0x00000590,
+at 0x0000019a : */ 0x18000000,0x00000590,
/*
MOVE FROM dsa_dataout+0x0170, WHEN DATA_OUT
-at 0x0000019e : */ 0x18000000,0x00000598,
+at 0x0000019c : */ 0x18000000,0x00000598,
/*
MOVE FROM dsa_dataout+0x0178, WHEN DATA_OUT
-at 0x000001a0 : */ 0x18000000,0x000005a0,
+at 0x0000019e : */ 0x18000000,0x000005a0,
/*
MOVE FROM dsa_dataout+0x0180, WHEN DATA_OUT
-at 0x000001a2 : */ 0x18000000,0x000005a8,
+at 0x000001a0 : */ 0x18000000,0x000005a8,
/*
MOVE FROM dsa_dataout+0x0188, WHEN DATA_OUT
-at 0x000001a4 : */ 0x18000000,0x000005b0,
+at 0x000001a2 : */ 0x18000000,0x000005b0,
/*
MOVE FROM dsa_dataout+0x0190, WHEN DATA_OUT
-at 0x000001a6 : */ 0x18000000,0x000005b8,
+at 0x000001a4 : */ 0x18000000,0x000005b8,
/*
MOVE FROM dsa_dataout+0x0198, WHEN DATA_OUT
-at 0x000001a8 : */ 0x18000000,0x000005c0,
+at 0x000001a6 : */ 0x18000000,0x000005c0,
/*
MOVE FROM dsa_dataout+0x01a0, WHEN DATA_OUT
-at 0x000001aa : */ 0x18000000,0x000005c8,
+at 0x000001a8 : */ 0x18000000,0x000005c8,
/*
MOVE FROM dsa_dataout+0x01a8, WHEN DATA_OUT
-at 0x000001ac : */ 0x18000000,0x000005d0,
+at 0x000001aa : */ 0x18000000,0x000005d0,
/*
MOVE FROM dsa_dataout+0x01b0, WHEN DATA_OUT
-at 0x000001ae : */ 0x18000000,0x000005d8,
+at 0x000001ac : */ 0x18000000,0x000005d8,
/*
MOVE FROM dsa_dataout+0x01b8, WHEN DATA_OUT
-at 0x000001b0 : */ 0x18000000,0x000005e0,
+at 0x000001ae : */ 0x18000000,0x000005e0,
/*
MOVE FROM dsa_dataout+0x01c0, WHEN DATA_OUT
-at 0x000001b2 : */ 0x18000000,0x000005e8,
+at 0x000001b0 : */ 0x18000000,0x000005e8,
/*
MOVE FROM dsa_dataout+0x01c8, WHEN DATA_OUT
-at 0x000001b4 : */ 0x18000000,0x000005f0,
+at 0x000001b2 : */ 0x18000000,0x000005f0,
/*
MOVE FROM dsa_dataout+0x01d0, WHEN DATA_OUT
-at 0x000001b6 : */ 0x18000000,0x000005f8,
+at 0x000001b4 : */ 0x18000000,0x000005f8,
/*
MOVE FROM dsa_dataout+0x01d8, WHEN DATA_OUT
-at 0x000001b8 : */ 0x18000000,0x00000600,
+at 0x000001b6 : */ 0x18000000,0x00000600,
/*
MOVE FROM dsa_dataout+0x01e0, WHEN DATA_OUT
-at 0x000001ba : */ 0x18000000,0x00000608,
+at 0x000001b8 : */ 0x18000000,0x00000608,
/*
MOVE FROM dsa_dataout+0x01e8, WHEN DATA_OUT
-at 0x000001bc : */ 0x18000000,0x00000610,
+at 0x000001ba : */ 0x18000000,0x00000610,
/*
MOVE FROM dsa_dataout+0x01f0, WHEN DATA_OUT
-at 0x000001be : */ 0x18000000,0x00000618,
+at 0x000001bc : */ 0x18000000,0x00000618,
/*
MOVE FROM dsa_dataout+0x01f8, WHEN DATA_OUT
-at 0x000001c0 : */ 0x18000000,0x00000620,
+at 0x000001be : */ 0x18000000,0x00000620,
/*
MOVE FROM dsa_dataout+0x0200, WHEN DATA_OUT
-at 0x000001c2 : */ 0x18000000,0x00000628,
+at 0x000001c0 : */ 0x18000000,0x00000628,
/*
MOVE FROM dsa_dataout+0x0208, WHEN DATA_OUT
-at 0x000001c4 : */ 0x18000000,0x00000630,
+at 0x000001c2 : */ 0x18000000,0x00000630,
/*
MOVE FROM dsa_dataout+0x0210, WHEN DATA_OUT
-at 0x000001c6 : */ 0x18000000,0x00000638,
+at 0x000001c4 : */ 0x18000000,0x00000638,
/*
MOVE FROM dsa_dataout+0x0218, WHEN DATA_OUT
-at 0x000001c8 : */ 0x18000000,0x00000640,
+at 0x000001c6 : */ 0x18000000,0x00000640,
/*
MOVE FROM dsa_dataout+0x0220, WHEN DATA_OUT
-at 0x000001ca : */ 0x18000000,0x00000648,
+at 0x000001c8 : */ 0x18000000,0x00000648,
/*
MOVE FROM dsa_dataout+0x0228, WHEN DATA_OUT
-at 0x000001cc : */ 0x18000000,0x00000650,
+at 0x000001ca : */ 0x18000000,0x00000650,
/*
MOVE FROM dsa_dataout+0x0230, WHEN DATA_OUT
-at 0x000001ce : */ 0x18000000,0x00000658,
+at 0x000001cc : */ 0x18000000,0x00000658,
/*
MOVE FROM dsa_dataout+0x0238, WHEN DATA_OUT
-at 0x000001d0 : */ 0x18000000,0x00000660,
+at 0x000001ce : */ 0x18000000,0x00000660,
/*
MOVE FROM dsa_dataout+0x0240, WHEN DATA_OUT
-at 0x000001d2 : */ 0x18000000,0x00000668,
+at 0x000001d0 : */ 0x18000000,0x00000668,
/*
MOVE FROM dsa_dataout+0x0248, WHEN DATA_OUT
-at 0x000001d4 : */ 0x18000000,0x00000670,
+at 0x000001d2 : */ 0x18000000,0x00000670,
/*
MOVE FROM dsa_dataout+0x0250, WHEN DATA_OUT
-at 0x000001d6 : */ 0x18000000,0x00000678,
+at 0x000001d4 : */ 0x18000000,0x00000678,
/*
MOVE FROM dsa_dataout+0x0258, WHEN DATA_OUT
-at 0x000001d8 : */ 0x18000000,0x00000680,
+at 0x000001d6 : */ 0x18000000,0x00000680,
/*
MOVE FROM dsa_dataout+0x0260, WHEN DATA_OUT
-at 0x000001da : */ 0x18000000,0x00000688,
+at 0x000001d8 : */ 0x18000000,0x00000688,
/*
MOVE FROM dsa_dataout+0x0268, WHEN DATA_OUT
-at 0x000001dc : */ 0x18000000,0x00000690,
+at 0x000001da : */ 0x18000000,0x00000690,
/*
MOVE FROM dsa_dataout+0x0270, WHEN DATA_OUT
-at 0x000001de : */ 0x18000000,0x00000698,
+at 0x000001dc : */ 0x18000000,0x00000698,
/*
MOVE FROM dsa_dataout+0x0278, WHEN DATA_OUT
-at 0x000001e0 : */ 0x18000000,0x000006a0,
+at 0x000001de : */ 0x18000000,0x000006a0,
/*
MOVE FROM dsa_dataout+0x0280, WHEN DATA_OUT
-at 0x000001e2 : */ 0x18000000,0x000006a8,
+at 0x000001e0 : */ 0x18000000,0x000006a8,
/*
MOVE FROM dsa_dataout+0x0288, WHEN DATA_OUT
-at 0x000001e4 : */ 0x18000000,0x000006b0,
+at 0x000001e2 : */ 0x18000000,0x000006b0,
/*
MOVE FROM dsa_dataout+0x0290, WHEN DATA_OUT
-at 0x000001e6 : */ 0x18000000,0x000006b8,
+at 0x000001e4 : */ 0x18000000,0x000006b8,
/*
MOVE FROM dsa_dataout+0x0298, WHEN DATA_OUT
-at 0x000001e8 : */ 0x18000000,0x000006c0,
+at 0x000001e6 : */ 0x18000000,0x000006c0,
/*
MOVE FROM dsa_dataout+0x02a0, WHEN DATA_OUT
-at 0x000001ea : */ 0x18000000,0x000006c8,
+at 0x000001e8 : */ 0x18000000,0x000006c8,
/*
MOVE FROM dsa_dataout+0x02a8, WHEN DATA_OUT
-at 0x000001ec : */ 0x18000000,0x000006d0,
+at 0x000001ea : */ 0x18000000,0x000006d0,
/*
MOVE FROM dsa_dataout+0x02b0, WHEN DATA_OUT
-at 0x000001ee : */ 0x18000000,0x000006d8,
+at 0x000001ec : */ 0x18000000,0x000006d8,
/*
MOVE FROM dsa_dataout+0x02b8, WHEN DATA_OUT
-at 0x000001f0 : */ 0x18000000,0x000006e0,
+at 0x000001ee : */ 0x18000000,0x000006e0,
/*
MOVE FROM dsa_dataout+0x02c0, WHEN DATA_OUT
-at 0x000001f2 : */ 0x18000000,0x000006e8,
+at 0x000001f0 : */ 0x18000000,0x000006e8,
/*
MOVE FROM dsa_dataout+0x02c8, WHEN DATA_OUT
-at 0x000001f4 : */ 0x18000000,0x000006f0,
+at 0x000001f2 : */ 0x18000000,0x000006f0,
/*
MOVE FROM dsa_dataout+0x02d0, WHEN DATA_OUT
-at 0x000001f6 : */ 0x18000000,0x000006f8,
+at 0x000001f4 : */ 0x18000000,0x000006f8,
/*
MOVE FROM dsa_dataout+0x02d8, WHEN DATA_OUT
-at 0x000001f8 : */ 0x18000000,0x00000700,
+at 0x000001f6 : */ 0x18000000,0x00000700,
/*
MOVE FROM dsa_dataout+0x02e0, WHEN DATA_OUT
-at 0x000001fa : */ 0x18000000,0x00000708,
+at 0x000001f8 : */ 0x18000000,0x00000708,
/*
MOVE FROM dsa_dataout+0x02e8, WHEN DATA_OUT
-at 0x000001fc : */ 0x18000000,0x00000710,
+at 0x000001fa : */ 0x18000000,0x00000710,
/*
MOVE FROM dsa_dataout+0x02f0, WHEN DATA_OUT
-at 0x000001fe : */ 0x18000000,0x00000718,
+at 0x000001fc : */ 0x18000000,0x00000718,
/*
MOVE FROM dsa_dataout+0x02f8, WHEN DATA_OUT
-at 0x00000200 : */ 0x18000000,0x00000720,
+at 0x000001fe : */ 0x18000000,0x00000720,
/*
MOVE FROM dsa_dataout+0x0300, WHEN DATA_OUT
-at 0x00000202 : */ 0x18000000,0x00000728,
+at 0x00000200 : */ 0x18000000,0x00000728,
/*
MOVE FROM dsa_dataout+0x0308, WHEN DATA_OUT
-at 0x00000204 : */ 0x18000000,0x00000730,
+at 0x00000202 : */ 0x18000000,0x00000730,
/*
MOVE FROM dsa_dataout+0x0310, WHEN DATA_OUT
-at 0x00000206 : */ 0x18000000,0x00000738,
+at 0x00000204 : */ 0x18000000,0x00000738,
/*
MOVE FROM dsa_dataout+0x0318, WHEN DATA_OUT
-at 0x00000208 : */ 0x18000000,0x00000740,
+at 0x00000206 : */ 0x18000000,0x00000740,
/*
MOVE FROM dsa_dataout+0x0320, WHEN DATA_OUT
-at 0x0000020a : */ 0x18000000,0x00000748,
+at 0x00000208 : */ 0x18000000,0x00000748,
/*
MOVE FROM dsa_dataout+0x0328, WHEN DATA_OUT
-at 0x0000020c : */ 0x18000000,0x00000750,
+at 0x0000020a : */ 0x18000000,0x00000750,
/*
MOVE FROM dsa_dataout+0x0330, WHEN DATA_OUT
-at 0x0000020e : */ 0x18000000,0x00000758,
+at 0x0000020c : */ 0x18000000,0x00000758,
/*
MOVE FROM dsa_dataout+0x0338, WHEN DATA_OUT
-at 0x00000210 : */ 0x18000000,0x00000760,
+at 0x0000020e : */ 0x18000000,0x00000760,
/*
MOVE FROM dsa_dataout+0x0340, WHEN DATA_OUT
-at 0x00000212 : */ 0x18000000,0x00000768,
+at 0x00000210 : */ 0x18000000,0x00000768,
/*
MOVE FROM dsa_dataout+0x0348, WHEN DATA_OUT
-at 0x00000214 : */ 0x18000000,0x00000770,
+at 0x00000212 : */ 0x18000000,0x00000770,
/*
MOVE FROM dsa_dataout+0x0350, WHEN DATA_OUT
-at 0x00000216 : */ 0x18000000,0x00000778,
+at 0x00000214 : */ 0x18000000,0x00000778,
/*
MOVE FROM dsa_dataout+0x0358, WHEN DATA_OUT
-at 0x00000218 : */ 0x18000000,0x00000780,
+at 0x00000216 : */ 0x18000000,0x00000780,
/*
MOVE FROM dsa_dataout+0x0360, WHEN DATA_OUT
-at 0x0000021a : */ 0x18000000,0x00000788,
+at 0x00000218 : */ 0x18000000,0x00000788,
/*
MOVE FROM dsa_dataout+0x0368, WHEN DATA_OUT
-at 0x0000021c : */ 0x18000000,0x00000790,
+at 0x0000021a : */ 0x18000000,0x00000790,
/*
MOVE FROM dsa_dataout+0x0370, WHEN DATA_OUT
-at 0x0000021e : */ 0x18000000,0x00000798,
+at 0x0000021c : */ 0x18000000,0x00000798,
/*
MOVE FROM dsa_dataout+0x0378, WHEN DATA_OUT
-at 0x00000220 : */ 0x18000000,0x000007a0,
+at 0x0000021e : */ 0x18000000,0x000007a0,
/*
MOVE FROM dsa_dataout+0x0380, WHEN DATA_OUT
-at 0x00000222 : */ 0x18000000,0x000007a8,
+at 0x00000220 : */ 0x18000000,0x000007a8,
/*
MOVE FROM dsa_dataout+0x0388, WHEN DATA_OUT
-at 0x00000224 : */ 0x18000000,0x000007b0,
+at 0x00000222 : */ 0x18000000,0x000007b0,
/*
MOVE FROM dsa_dataout+0x0390, WHEN DATA_OUT
-at 0x00000226 : */ 0x18000000,0x000007b8,
+at 0x00000224 : */ 0x18000000,0x000007b8,
/*
MOVE FROM dsa_dataout+0x0398, WHEN DATA_OUT
-at 0x00000228 : */ 0x18000000,0x000007c0,
+at 0x00000226 : */ 0x18000000,0x000007c0,
/*
MOVE FROM dsa_dataout+0x03a0, WHEN DATA_OUT
-at 0x0000022a : */ 0x18000000,0x000007c8,
+at 0x00000228 : */ 0x18000000,0x000007c8,
/*
MOVE FROM dsa_dataout+0x03a8, WHEN DATA_OUT
-at 0x0000022c : */ 0x18000000,0x000007d0,
+at 0x0000022a : */ 0x18000000,0x000007d0,
/*
MOVE FROM dsa_dataout+0x03b0, WHEN DATA_OUT
-at 0x0000022e : */ 0x18000000,0x000007d8,
+at 0x0000022c : */ 0x18000000,0x000007d8,
/*
MOVE FROM dsa_dataout+0x03b8, WHEN DATA_OUT
-at 0x00000230 : */ 0x18000000,0x000007e0,
+at 0x0000022e : */ 0x18000000,0x000007e0,
/*
MOVE FROM dsa_dataout+0x03c0, WHEN DATA_OUT
-at 0x00000232 : */ 0x18000000,0x000007e8,
+at 0x00000230 : */ 0x18000000,0x000007e8,
/*
MOVE FROM dsa_dataout+0x03c8, WHEN DATA_OUT
-at 0x00000234 : */ 0x18000000,0x000007f0,
+at 0x00000232 : */ 0x18000000,0x000007f0,
/*
MOVE FROM dsa_dataout+0x03d0, WHEN DATA_OUT
-at 0x00000236 : */ 0x18000000,0x000007f8,
+at 0x00000234 : */ 0x18000000,0x000007f8,
/*
MOVE FROM dsa_dataout+0x03d8, WHEN DATA_OUT
-at 0x00000238 : */ 0x18000000,0x00000800,
+at 0x00000236 : */ 0x18000000,0x00000800,
/*
MOVE FROM dsa_dataout+0x03e0, WHEN DATA_OUT
-at 0x0000023a : */ 0x18000000,0x00000808,
+at 0x00000238 : */ 0x18000000,0x00000808,
/*
MOVE FROM dsa_dataout+0x03e8, WHEN DATA_OUT
-at 0x0000023c : */ 0x18000000,0x00000810,
+at 0x0000023a : */ 0x18000000,0x00000810,
/*
MOVE FROM dsa_dataout+0x03f0, WHEN DATA_OUT
-at 0x0000023e : */ 0x18000000,0x00000818,
+at 0x0000023c : */ 0x18000000,0x00000818,
/*
MOVE FROM dsa_dataout+0x03f8, WHEN DATA_OUT
-at 0x00000240 : */ 0x18000000,0x00000820,
+at 0x0000023e : */ 0x18000000,0x00000820,
/*
ENTRY end_data_trans
end_data_trans:
redo_msgin3:
JUMP get_status, WHEN STATUS
-at 0x00000242 : */ 0x830b0000,0x000000a0,
+at 0x00000240 : */ 0x830b0000,0x00000098,
/*
JUMP get_msgin3, WHEN MSG_IN
-at 0x00000244 : */ 0x870b0000,0x00000b20,
+at 0x00000242 : */ 0x870b0000,0x00000b78,
/*
INT int_data_bad_phase
-at 0x00000246 : */ 0x98080000,0xab93000b,
+at 0x00000244 : */ 0x98080000,0xab93000b,
/*
get_msgin1:
MOVE SCRATCH0 | had_msgin TO SCRATCH0
-at 0x00000248 : */ 0x7a344000,0x00000000,
+at 0x00000246 : */ 0x7a344000,0x00000000,
/*
MOVE 1, msgin_buf, WHEN MSG_IN
-at 0x0000024a : */ 0x0f000001,0x00000000,
+at 0x00000248 : */ 0x0f000001,0x00000000,
/*
JUMP ext_msg1, IF 0x01 ; Extended Message
-at 0x0000024c : */ 0x800c0001,0x00000968,
+at 0x0000024a : */ 0x800c0001,0x00000960,
/*
JUMP ignore_msg1, IF 0x02 ; Save Data Pointers
-at 0x0000024e : */ 0x800c0002,0x00000958,
+at 0x0000024c : */ 0x800c0002,0x00000950,
/*
JUMP ignore_msg1, IF 0x03 ; Save Restore Pointers
-at 0x00000250 : */ 0x800c0003,0x00000958,
+at 0x0000024e : */ 0x800c0003,0x00000950,
/*
JUMP disc1, IF 0x04 ; Disconnect
-at 0x00000252 : */ 0x800c0004,0x000009c8,
+at 0x00000250 : */ 0x800c0004,0x000009f0,
/*
INT int_bad_msg1
-at 0x00000254 : */ 0x98080000,0xab930006,
+at 0x00000252 : */ 0x98080000,0xab930006,
/*
ignore_msg1:
CLEAR ACK
-at 0x00000256 : */ 0x60000040,0x00000000,
+at 0x00000254 : */ 0x60000040,0x00000000,
/*
JUMP redo_msgin1
-at 0x00000258 : */ 0x80080000,0x00000058,
+at 0x00000256 : */ 0x80080000,0x00000050,
/*
ext_msg1:
MOVE SCRATCH0 | had_extmsg TO SCRATCH0
-at 0x0000025a : */ 0x7a348000,0x00000000,
+at 0x00000258 : */ 0x7a348000,0x00000000,
/*
CLEAR ACK
-at 0x0000025c : */ 0x60000040,0x00000000,
+at 0x0000025a : */ 0x60000040,0x00000000,
/*
MOVE 1, msgin_buf + 1, WHEN MSG_IN
-at 0x0000025e : */ 0x0f000001,0x00000001,
+at 0x0000025c : */ 0x0f000001,0x00000001,
/*
- JUMP ext_msg1a, IF 0x03
+ JUMP reject_msg1, IF NOT 0x03 ; Only handle SDTR
-at 0x00000260 : */ 0x800c0003,0x00000990,
+at 0x0000025e : */ 0x80040003,0x000009b0,
/*
- INT int_bad_extmsg1a
+ CLEAR ACK
-at 0x00000262 : */ 0x98080000,0xab930000,
+at 0x00000260 : */ 0x60000040,0x00000000,
+/*
+ MOVE 1, msgin_buf + 2, WHEN MSG_IN
+
+at 0x00000262 : */ 0x0f000001,0x00000002,
+/*
+ JUMP reject_msg1, IF NOT 0x01 ; Only handle SDTR
+
+at 0x00000264 : */ 0x80040001,0x000009b0,
/*
-ext_msg1a:
CLEAR ACK
-at 0x00000264 : */ 0x60000040,0x00000000,
+at 0x00000266 : */ 0x60000040,0x00000000,
/*
- MOVE 1, msgin_buf + 2, WHEN MSG_IN
+ MOVE 2, msgin_buf + 3, WHEN MSG_IN
-at 0x00000266 : */ 0x0f000001,0x00000002,
+at 0x00000268 : */ 0x0f000002,0x00000003,
/*
- JUMP ext_msg1b, IF 0x01 ; Must be SDTR
+ INT int_msg_sdtr1
+
+at 0x0000026a : */ 0x98080000,0xab93000c,
+/*
+reject_msg1:
+ MOVE SCRATCH1 | did_reject TO SCRATCH1
-at 0x00000268 : */ 0x800c0001,0x000009b0,
+at 0x0000026c : */ 0x7a350100,0x00000000,
/*
- INT int_bad_extmsg1b
+ SET ATN
-at 0x0000026a : */ 0x98080000,0xab930001,
+at 0x0000026e : */ 0x58000008,0x00000000,
/*
-ext_msg1b:
CLEAR ACK
-at 0x0000026c : */ 0x60000040,0x00000000,
+at 0x00000270 : */ 0x60000040,0x00000000,
/*
- MOVE 2, msgin_buf + 3, WHEN MSG_IN
+ JUMP reject_msg1a, WHEN NOT MSG_IN
-at 0x0000026e : */ 0x0f000002,0x00000003,
+at 0x00000272 : */ 0x87030000,0x000009e0,
/*
- INT int_msg_sdtr1
+ MOVE 1, msgin_buf + 7, WHEN MSG_IN
-at 0x00000270 : */ 0x98080000,0xab93000c,
+at 0x00000274 : */ 0x0f000001,0x00000007,
+/*
+ JUMP reject_msg1
+
+at 0x00000276 : */ 0x80080000,0x000009b0,
+/*
+reject_msg1a:
+ MOVE 1, msg_reject, WHEN MSG_OUT
+
+at 0x00000278 : */ 0x0e000001,0x00000000,
+/*
+ JUMP redo_msgin1
+
+at 0x0000027a : */ 0x80080000,0x00000050,
/*
disc1:
CLEAR ACK
-at 0x00000272 : */ 0x60000040,0x00000000,
+at 0x0000027c : */ 0x60000040,0x00000000,
/*
ENTRY wait_disc1
wait_disc1:
WAIT DISCONNECT
-at 0x00000274 : */ 0x48000000,0x00000000,
+at 0x0000027e : */ 0x48000000,0x00000000,
/*
INT int_disc1
-at 0x00000276 : */ 0x98080000,0xab930019,
+at 0x00000280 : */ 0x98080000,0xab930019,
/*
ENTRY resume_msgin1a
resume_msgin1a:
CLEAR ACK
-at 0x00000278 : */ 0x60000040,0x00000000,
+at 0x00000282 : */ 0x60000040,0x00000000,
/*
JUMP redo_msgin1
-at 0x0000027a : */ 0x80080000,0x00000058,
+at 0x00000284 : */ 0x80080000,0x00000050,
/*
ENTRY resume_msgin1b
resume_msgin1b:
SET ATN
-at 0x0000027c : */ 0x58000008,0x00000000,
+at 0x00000286 : */ 0x58000008,0x00000000,
/*
CLEAR ACK
-at 0x0000027e : */ 0x60000040,0x00000000,
+at 0x00000288 : */ 0x60000040,0x00000000,
/*
INT int_no_msgout1, WHEN NOT MSG_OUT
-at 0x00000280 : */ 0x9e030000,0xab93000f,
+at 0x0000028a : */ 0x9e030000,0xab93000f,
/*
MOVE SCRATCH0 | had_msgout TO SCRATCH0
-at 0x00000282 : */ 0x7a340200,0x00000000,
+at 0x0000028c : */ 0x7a340200,0x00000000,
/*
MOVE FROM dsa_msgout, when MSG_OUT
-at 0x00000284 : */ 0x1e000000,0x00000008,
+at 0x0000028e : */ 0x1e000000,0x00000008,
/*
JUMP redo_msgin1
-at 0x00000286 : */ 0x80080000,0x00000058,
+at 0x00000290 : */ 0x80080000,0x00000050,
/*
get_msgin2:
MOVE SCRATCH0 | had_msgin TO SCRATCH0
-at 0x00000288 : */ 0x7a344000,0x00000000,
+at 0x00000292 : */ 0x7a344000,0x00000000,
/*
MOVE 1, msgin_buf, WHEN MSG_IN
-at 0x0000028a : */ 0x0f000001,0x00000000,
+at 0x00000294 : */ 0x0f000001,0x00000000,
/*
JUMP ext_msg2, IF 0x01 ; Extended Message
-at 0x0000028c : */ 0x800c0001,0x00000a68,
+at 0x00000296 : */ 0x800c0001,0x00000a90,
/*
JUMP ignore_msg2, IF 0x02 ; Save Data Pointers
-at 0x0000028e : */ 0x800c0002,0x00000a58,
+at 0x00000298 : */ 0x800c0002,0x00000a80,
/*
JUMP ignore_msg2, IF 0x03 ; Save Restore Pointers
-at 0x00000290 : */ 0x800c0003,0x00000a58,
+at 0x0000029a : */ 0x800c0003,0x00000a80,
/*
JUMP disc2, IF 0x04 ; Disconnect
-at 0x00000292 : */ 0x800c0004,0x00000ac8,
+at 0x0000029c : */ 0x800c0004,0x00000b20,
/*
INT int_bad_msg2
-at 0x00000294 : */ 0x98080000,0xab930007,
+at 0x0000029e : */ 0x98080000,0xab930007,
/*
ignore_msg2:
CLEAR ACK
-at 0x00000296 : */ 0x60000040,0x00000000,
+at 0x000002a0 : */ 0x60000040,0x00000000,
/*
JUMP redo_msgin2
-at 0x00000298 : */ 0x80080000,0x00000078,
+at 0x000002a2 : */ 0x80080000,0x00000070,
/*
ext_msg2:
MOVE SCRATCH0 | had_extmsg TO SCRATCH0
-at 0x0000029a : */ 0x7a348000,0x00000000,
+at 0x000002a4 : */ 0x7a348000,0x00000000,
/*
CLEAR ACK
-at 0x0000029c : */ 0x60000040,0x00000000,
+at 0x000002a6 : */ 0x60000040,0x00000000,
/*
MOVE 1, msgin_buf + 1, WHEN MSG_IN
-at 0x0000029e : */ 0x0f000001,0x00000001,
+at 0x000002a8 : */ 0x0f000001,0x00000001,
+/*
+ JUMP reject_msg2, IF NOT 0x03 ; Only handle SDTR
+
+at 0x000002aa : */ 0x80040003,0x00000ae0,
+/*
+ CLEAR ACK
+
+at 0x000002ac : */ 0x60000040,0x00000000,
/*
- JUMP ext_msg2a, IF 0x03
+ MOVE 1, msgin_buf + 2, WHEN MSG_IN
-at 0x000002a0 : */ 0x800c0003,0x00000a90,
+at 0x000002ae : */ 0x0f000001,0x00000002,
/*
- INT int_bad_extmsg2a
+ JUMP reject_msg2, IF NOT 0x01 ; Only handle SDTR
-at 0x000002a2 : */ 0x98080000,0xab930002,
+at 0x000002b0 : */ 0x80040001,0x00000ae0,
/*
-ext_msg2a:
CLEAR ACK
-at 0x000002a4 : */ 0x60000040,0x00000000,
+at 0x000002b2 : */ 0x60000040,0x00000000,
/*
- MOVE 1, msgin_buf + 2, WHEN MSG_IN
+ MOVE 2, msgin_buf + 3, WHEN MSG_IN
+
+at 0x000002b4 : */ 0x0f000002,0x00000003,
+/*
+ INT int_msg_sdtr2
-at 0x000002a6 : */ 0x0f000001,0x00000002,
+at 0x000002b6 : */ 0x98080000,0xab93000d,
/*
- JUMP ext_msg2b, IF 0x01 ; Must be SDTR
+reject_msg2:
+ MOVE SCRATCH1 | did_reject TO SCRATCH1
-at 0x000002a8 : */ 0x800c0001,0x00000ab0,
+at 0x000002b8 : */ 0x7a350100,0x00000000,
/*
- INT int_bad_extmsg2b
+ SET ATN
-at 0x000002aa : */ 0x98080000,0xab930003,
+at 0x000002ba : */ 0x58000008,0x00000000,
/*
-ext_msg2b:
CLEAR ACK
-at 0x000002ac : */ 0x60000040,0x00000000,
+at 0x000002bc : */ 0x60000040,0x00000000,
/*
- MOVE 2, msgin_buf + 3, WHEN MSG_IN
+ JUMP reject_msg2a, WHEN NOT MSG_IN
-at 0x000002ae : */ 0x0f000002,0x00000003,
+at 0x000002be : */ 0x87030000,0x00000b10,
/*
- INT int_msg_sdtr2
+ MOVE 1, msgin_buf + 7, WHEN MSG_IN
+
+at 0x000002c0 : */ 0x0f000001,0x00000007,
+/*
+ JUMP reject_msg2
+
+at 0x000002c2 : */ 0x80080000,0x00000ae0,
+/*
+reject_msg2a:
+ MOVE 1, msg_reject, WHEN MSG_OUT
+
+at 0x000002c4 : */ 0x0e000001,0x00000000,
+/*
+ JUMP redo_msgin2
-at 0x000002b0 : */ 0x98080000,0xab93000d,
+at 0x000002c6 : */ 0x80080000,0x00000070,
/*
disc2:
CLEAR ACK
-at 0x000002b2 : */ 0x60000040,0x00000000,
+at 0x000002c8 : */ 0x60000040,0x00000000,
/*
ENTRY wait_disc2
wait_disc2:
WAIT DISCONNECT
-at 0x000002b4 : */ 0x48000000,0x00000000,
+at 0x000002ca : */ 0x48000000,0x00000000,
/*
INT int_disc2
-at 0x000002b6 : */ 0x98080000,0xab93001a,
+at 0x000002cc : */ 0x98080000,0xab93001a,
/*
ENTRY resume_msgin2a
resume_msgin2a:
CLEAR ACK
-at 0x000002b8 : */ 0x60000040,0x00000000,
+at 0x000002ce : */ 0x60000040,0x00000000,
/*
JUMP redo_msgin2
-at 0x000002ba : */ 0x80080000,0x00000078,
+at 0x000002d0 : */ 0x80080000,0x00000070,
/*
ENTRY resume_msgin2b
resume_msgin2b:
SET ATN
-at 0x000002bc : */ 0x58000008,0x00000000,
+at 0x000002d2 : */ 0x58000008,0x00000000,
/*
CLEAR ACK
-at 0x000002be : */ 0x60000040,0x00000000,
+at 0x000002d4 : */ 0x60000040,0x00000000,
/*
INT int_no_msgout2, WHEN NOT MSG_OUT
-at 0x000002c0 : */ 0x9e030000,0xab930010,
+at 0x000002d6 : */ 0x9e030000,0xab930010,
/*
MOVE SCRATCH0 | had_msgout TO SCRATCH0
-at 0x000002c2 : */ 0x7a340200,0x00000000,
+at 0x000002d8 : */ 0x7a340200,0x00000000,
/*
MOVE FROM dsa_msgout, when MSG_OUT
-at 0x000002c4 : */ 0x1e000000,0x00000008,
+at 0x000002da : */ 0x1e000000,0x00000008,
/*
JUMP redo_msgin2
-at 0x000002c6 : */ 0x80080000,0x00000078,
+at 0x000002dc : */ 0x80080000,0x00000070,
/*
get_msgin3:
MOVE SCRATCH0 | had_msgin TO SCRATCH0
-at 0x000002c8 : */ 0x7a344000,0x00000000,
+at 0x000002de : */ 0x7a344000,0x00000000,
/*
MOVE 1, msgin_buf, WHEN MSG_IN
-at 0x000002ca : */ 0x0f000001,0x00000000,
+at 0x000002e0 : */ 0x0f000001,0x00000000,
/*
JUMP ext_msg3, IF 0x01 ; Extended Message
-at 0x000002cc : */ 0x800c0001,0x00000b68,
+at 0x000002e2 : */ 0x800c0001,0x00000bc0,
/*
JUMP ignore_msg3, IF 0x02 ; Save Data Pointers
-at 0x000002ce : */ 0x800c0002,0x00000b58,
+at 0x000002e4 : */ 0x800c0002,0x00000bb0,
/*
JUMP ignore_msg3, IF 0x03 ; Save Restore Pointers
-at 0x000002d0 : */ 0x800c0003,0x00000b58,
+at 0x000002e6 : */ 0x800c0003,0x00000bb0,
/*
JUMP disc3, IF 0x04 ; Disconnect
-at 0x000002d2 : */ 0x800c0004,0x00000bc8,
+at 0x000002e8 : */ 0x800c0004,0x00000c50,
/*
INT int_bad_msg3
-at 0x000002d4 : */ 0x98080000,0xab930008,
+at 0x000002ea : */ 0x98080000,0xab930008,
/*
ignore_msg3:
CLEAR ACK
-at 0x000002d6 : */ 0x60000040,0x00000000,
+at 0x000002ec : */ 0x60000040,0x00000000,
/*
JUMP redo_msgin3
-at 0x000002d8 : */ 0x80080000,0x00000908,
+at 0x000002ee : */ 0x80080000,0x00000900,
/*
ext_msg3:
MOVE SCRATCH0 | had_extmsg TO SCRATCH0
-at 0x000002da : */ 0x7a348000,0x00000000,
+at 0x000002f0 : */ 0x7a348000,0x00000000,
/*
CLEAR ACK
-at 0x000002dc : */ 0x60000040,0x00000000,
+at 0x000002f2 : */ 0x60000040,0x00000000,
/*
MOVE 1, msgin_buf + 1, WHEN MSG_IN
-at 0x000002de : */ 0x0f000001,0x00000001,
+at 0x000002f4 : */ 0x0f000001,0x00000001,
/*
- JUMP ext_msg3a, IF 0x03
+ JUMP reject_msg3, IF NOT 0x03 ; Only handle SDTR
-at 0x000002e0 : */ 0x800c0003,0x00000b90,
+at 0x000002f6 : */ 0x80040003,0x00000c10,
/*
- INT int_bad_extmsg3a
+ CLEAR ACK
-at 0x000002e2 : */ 0x98080000,0xab930004,
+at 0x000002f8 : */ 0x60000040,0x00000000,
+/*
+ MOVE 1, msgin_buf + 2, WHEN MSG_IN
+
+at 0x000002fa : */ 0x0f000001,0x00000002,
+/*
+ JUMP reject_msg3, IF NOT 0x01 ; Only handle SDTR
+
+at 0x000002fc : */ 0x80040001,0x00000c10,
/*
-ext_msg3a:
CLEAR ACK
-at 0x000002e4 : */ 0x60000040,0x00000000,
+at 0x000002fe : */ 0x60000040,0x00000000,
/*
- MOVE 1, msgin_buf + 2, WHEN MSG_IN
+ MOVE 2, msgin_buf + 3, WHEN MSG_IN
+
+at 0x00000300 : */ 0x0f000002,0x00000003,
+/*
+ INT int_msg_sdtr3
-at 0x000002e6 : */ 0x0f000001,0x00000002,
+at 0x00000302 : */ 0x98080000,0xab93000e,
/*
- JUMP ext_msg3b, IF 0x01 ; Must be SDTR
+reject_msg3:
+ MOVE SCRATCH1 | did_reject TO SCRATCH1
-at 0x000002e8 : */ 0x800c0001,0x00000bb0,
+at 0x00000304 : */ 0x7a350100,0x00000000,
/*
- INT int_bad_extmsg3b
+ SET ATN
-at 0x000002ea : */ 0x98080000,0xab930005,
+at 0x00000306 : */ 0x58000008,0x00000000,
/*
-ext_msg3b:
CLEAR ACK
-at 0x000002ec : */ 0x60000040,0x00000000,
+at 0x00000308 : */ 0x60000040,0x00000000,
/*
- MOVE 2, msgin_buf + 3, WHEN MSG_IN
+ JUMP reject_msg3a, WHEN NOT MSG_IN
-at 0x000002ee : */ 0x0f000002,0x00000003,
+at 0x0000030a : */ 0x87030000,0x00000c40,
/*
- INT int_msg_sdtr3
+ MOVE 1, msgin_buf + 7, WHEN MSG_IN
+
+at 0x0000030c : */ 0x0f000001,0x00000007,
+/*
+ JUMP reject_msg3
+
+at 0x0000030e : */ 0x80080000,0x00000c10,
+/*
+reject_msg3a:
+ MOVE 1, msg_reject, WHEN MSG_OUT
-at 0x000002f0 : */ 0x98080000,0xab93000e,
+at 0x00000310 : */ 0x0e000001,0x00000000,
+/*
+ JUMP redo_msgin3
+
+at 0x00000312 : */ 0x80080000,0x00000900,
/*
disc3:
CLEAR ACK
-at 0x000002f2 : */ 0x60000040,0x00000000,
+at 0x00000314 : */ 0x60000040,0x00000000,
/*
ENTRY wait_disc3
wait_disc3:
WAIT DISCONNECT
-at 0x000002f4 : */ 0x48000000,0x00000000,
+at 0x00000316 : */ 0x48000000,0x00000000,
/*
INT int_disc3
-at 0x000002f6 : */ 0x98080000,0xab93001b,
+at 0x00000318 : */ 0x98080000,0xab93001b,
/*
ENTRY resume_msgin3a
resume_msgin3a:
CLEAR ACK
-at 0x000002f8 : */ 0x60000040,0x00000000,
+at 0x0000031a : */ 0x60000040,0x00000000,
/*
JUMP redo_msgin3
-at 0x000002fa : */ 0x80080000,0x00000908,
+at 0x0000031c : */ 0x80080000,0x00000900,
/*
ENTRY resume_msgin3b
resume_msgin3b:
SET ATN
-at 0x000002fc : */ 0x58000008,0x00000000,
+at 0x0000031e : */ 0x58000008,0x00000000,
/*
CLEAR ACK
-at 0x000002fe : */ 0x60000040,0x00000000,
+at 0x00000320 : */ 0x60000040,0x00000000,
/*
INT int_no_msgout3, WHEN NOT MSG_OUT
-at 0x00000300 : */ 0x9e030000,0xab930011,
+at 0x00000322 : */ 0x9e030000,0xab930011,
/*
MOVE SCRATCH0 | had_msgout TO SCRATCH0
-at 0x00000302 : */ 0x7a340200,0x00000000,
+at 0x00000324 : */ 0x7a340200,0x00000000,
/*
MOVE FROM dsa_msgout, when MSG_OUT
-at 0x00000304 : */ 0x1e000000,0x00000008,
+at 0x00000326 : */ 0x1e000000,0x00000008,
/*
JUMP redo_msgin3
-at 0x00000306 : */ 0x80080000,0x00000908,
+at 0x00000328 : */ 0x80080000,0x00000900,
/*
ENTRY resume_rej_ident
resume_rej_ident:
CLEAR ATN
-at 0x00000308 : */ 0x60000008,0x00000000,
+at 0x0000032a : */ 0x60000008,0x00000000,
/*
MOVE 1, msgin_buf, WHEN MSG_IN
-at 0x0000030a : */ 0x0f000001,0x00000000,
+at 0x0000032c : */ 0x0f000001,0x00000000,
/*
INT int_not_rej, IF NOT 0x07 ; Reject
-at 0x0000030c : */ 0x98040007,0xab93001c,
+at 0x0000032e : */ 0x98040007,0xab93001c,
/*
CLEAR ACK
-at 0x0000030e : */ 0x60000040,0x00000000,
+at 0x00000330 : */ 0x60000040,0x00000000,
/*
JUMP done_ident
-at 0x00000310 : */ 0x80080000,0x00000050,
+at 0x00000332 : */ 0x80080000,0x00000048,
/*
ENTRY reselect
@@ -1716,73 +1784,92 @@
; Disable selection timer
MOVE CTEST7 | 0x10 TO CTEST7
-at 0x00000312 : */ 0x7a1b1000,0x00000000,
+at 0x00000334 : */ 0x7a1b1000,0x00000000,
/*
WAIT RESELECT resel_err
-at 0x00000314 : */ 0x50000000,0x00000c70,
+at 0x00000336 : */ 0x50000000,0x00000cf8,
/*
INT int_resel_not_msgin, WHEN NOT MSG_IN
-at 0x00000316 : */ 0x9f030000,0xab930016,
+at 0x00000338 : */ 0x9f030000,0xab930016,
/*
MOVE 1, reselected_identify, WHEN MSG_IN
-at 0x00000318 : */ 0x0f000001,0x00000000,
+at 0x0000033a : */ 0x0f000001,0x00000000,
/*
INT int_reselected
-at 0x0000031a : */ 0x98080000,0xab930017,
+at 0x0000033c : */ 0x98080000,0xab930017,
/*
resel_err:
MOVE CTEST2 & 0x40 TO SFBR
-at 0x0000031c : */ 0x74164000,0x00000000,
+at 0x0000033e : */ 0x74164000,0x00000000,
/*
JUMP selected, IF 0x00
-at 0x0000031e : */ 0x800c0000,0x00000cb0,
+at 0x00000340 : */ 0x800c0000,0x00000d38,
/*
MOVE SFBR & 0 TO SFBR
-at 0x00000320 : */ 0x7c080000,0x00000000,
+at 0x00000342 : */ 0x7c080000,0x00000000,
/*
ENTRY patch_new_dsa
patch_new_dsa:
MOVE SFBR | 0x11 TO DSA0
-at 0x00000322 : */ 0x6a101100,0x00000000,
+at 0x00000344 : */ 0x6a101100,0x00000000,
/*
MOVE SFBR | 0x22 TO DSA1
-at 0x00000324 : */ 0x6a112200,0x00000000,
+at 0x00000346 : */ 0x6a112200,0x00000000,
/*
MOVE SFBR | 0x33 TO DSA2
-at 0x00000326 : */ 0x6a123300,0x00000000,
+at 0x00000348 : */ 0x6a123300,0x00000000,
/*
MOVE SFBR | 0x44 TO DSA3
-at 0x00000328 : */ 0x6a134400,0x00000000,
+at 0x0000034a : */ 0x6a134400,0x00000000,
/*
JUMP do_select
-at 0x0000032a : */ 0x80080000,0x00000000,
+at 0x0000034c : */ 0x80080000,0x00000000,
/*
selected:
INT int_selected
-at 0x0000032c : */ 0x98080000,0xab930018,
+at 0x0000034e : */ 0x98080000,0xab930018,
+/*
+
+ENTRY test1
+test1:
+ MOVE MEMORY 4, test1_src, test1_dst
+
+at 0x00000350 : */ 0xc0000004,0x00000000,0x00000000,
+/*
+ INT int_test1
+
+at 0x00000353 : */ 0x98080000,0xab93001d,
+};
+
+#define A_did_reject 0x00000001
+static u32 A_did_reject_used[] __attribute((unused)) = {
+ 0x0000026c,
+ 0x000002b8,
+ 0x00000304,
};
#define A_dsa_cmnd 0x00000010
static u32 A_dsa_cmnd_used[] __attribute((unused)) = {
- 0x0000001d,
+ 0x0000001b,
};
#define A_dsa_datain 0x00000028
static u32 A_dsa_datain_used[] __attribute((unused)) = {
+ 0x0000003b,
0x0000003d,
0x0000003f,
0x00000041,
@@ -1910,11 +1997,11 @@
0x00000135,
0x00000137,
0x00000139,
- 0x0000013b,
};
#define A_dsa_dataout 0x00000428
static u32 A_dsa_dataout_used[] __attribute((unused)) = {
+ 0x00000141,
0x00000143,
0x00000145,
0x00000147,
@@ -2042,25 +2129,24 @@
0x0000023b,
0x0000023d,
0x0000023f,
- 0x00000241,
};
#define A_dsa_msgin 0x00000020
static u32 A_dsa_msgin_used[] __attribute((unused)) = {
- 0x0000002f,
+ 0x0000002d,
};
#define A_dsa_msgout 0x00000008
static u32 A_dsa_msgout_used[] __attribute((unused)) = {
- 0x00000013,
- 0x00000285,
- 0x000002c5,
- 0x00000305,
+ 0x00000011,
+ 0x0000028f,
+ 0x000002db,
+ 0x00000327,
};
#define A_dsa_select 0x00000000
static u32 A_dsa_select_used[] __attribute((unused)) = {
- 0x00000006,
+ 0x00000004,
};
#define A_dsa_size 0x00000828
@@ -2069,285 +2155,290 @@
#define A_dsa_status 0x00000018
static u32 A_dsa_status_used[] __attribute((unused)) = {
- 0x0000002b,
+ 0x00000029,
};
#define A_had_cmdout 0x00000004
static u32 A_had_cmdout_used[] __attribute((unused)) = {
- 0x0000001a,
+ 0x00000018,
};
#define A_had_datain 0x00000008
static u32 A_had_datain_used[] __attribute((unused)) = {
- 0x00000038,
+ 0x00000036,
};
#define A_had_dataout 0x00000010
static u32 A_had_dataout_used[] __attribute((unused)) = {
- 0x0000013e,
+ 0x0000013c,
};
#define A_had_extmsg 0x00000080
static u32 A_had_extmsg_used[] __attribute((unused)) = {
- 0x0000025a,
- 0x0000029a,
- 0x000002da,
+ 0x00000258,
+ 0x000002a4,
+ 0x000002f0,
};
#define A_had_msgin 0x00000040
static u32 A_had_msgin_used[] __attribute((unused)) = {
- 0x00000248,
- 0x00000288,
- 0x000002c8,
+ 0x00000246,
+ 0x00000292,
+ 0x000002de,
};
#define A_had_msgout 0x00000002
static u32 A_had_msgout_used[] __attribute((unused)) = {
- 0x00000010,
- 0x00000282,
- 0x000002c2,
- 0x00000302,
+ 0x0000000e,
+ 0x0000028c,
+ 0x000002d8,
+ 0x00000324,
};
#define A_had_select 0x00000001
static u32 A_had_select_used[] __attribute((unused)) = {
- 0x0000000c,
+ 0x0000000a,
};
#define A_had_status 0x00000020
static u32 A_had_status_used[] __attribute((unused)) = {
};
-#define A_int_bad_extmsg1a 0xab930000
-static u32 A_int_bad_extmsg1a_used[] __attribute((unused)) = {
- 0x00000263,
-};
-
-#define A_int_bad_extmsg1b 0xab930001
-static u32 A_int_bad_extmsg1b_used[] __attribute((unused)) = {
- 0x0000026b,
-};
-
-#define A_int_bad_extmsg2a 0xab930002
-static u32 A_int_bad_extmsg2a_used[] __attribute((unused)) = {
- 0x000002a3,
-};
-
-#define A_int_bad_extmsg2b 0xab930003
-static u32 A_int_bad_extmsg2b_used[] __attribute((unused)) = {
- 0x000002ab,
-};
-
-#define A_int_bad_extmsg3a 0xab930004
-static u32 A_int_bad_extmsg3a_used[] __attribute((unused)) = {
- 0x000002e3,
-};
-
-#define A_int_bad_extmsg3b 0xab930005
-static u32 A_int_bad_extmsg3b_used[] __attribute((unused)) = {
- 0x000002eb,
-};
-
#define A_int_bad_msg1 0xab930006
static u32 A_int_bad_msg1_used[] __attribute((unused)) = {
- 0x00000255,
+ 0x00000253,
};
#define A_int_bad_msg2 0xab930007
static u32 A_int_bad_msg2_used[] __attribute((unused)) = {
- 0x00000295,
+ 0x0000029f,
};
#define A_int_bad_msg3 0xab930008
static u32 A_int_bad_msg3_used[] __attribute((unused)) = {
- 0x000002d5,
+ 0x000002eb,
};
#define A_int_cmd_bad_phase 0xab930009
static u32 A_int_cmd_bad_phase_used[] __attribute((unused)) = {
- 0x00000027,
+ 0x00000025,
};
#define A_int_cmd_complete 0xab93000a
static u32 A_int_cmd_complete_used[] __attribute((unused)) = {
- 0x00000037,
+ 0x00000035,
};
#define A_int_data_bad_phase 0xab93000b
static u32 A_int_data_bad_phase_used[] __attribute((unused)) = {
- 0x00000247,
+ 0x00000245,
};
#define A_int_disc1 0xab930019
static u32 A_int_disc1_used[] __attribute((unused)) = {
- 0x00000277,
+ 0x00000281,
};
#define A_int_disc2 0xab93001a
static u32 A_int_disc2_used[] __attribute((unused)) = {
- 0x000002b7,
+ 0x000002cd,
};
#define A_int_disc3 0xab93001b
static u32 A_int_disc3_used[] __attribute((unused)) = {
- 0x000002f7,
+ 0x00000319,
};
#define A_int_msg_sdtr1 0xab93000c
static u32 A_int_msg_sdtr1_used[] __attribute((unused)) = {
- 0x00000271,
+ 0x0000026b,
};
#define A_int_msg_sdtr2 0xab93000d
static u32 A_int_msg_sdtr2_used[] __attribute((unused)) = {
- 0x000002b1,
+ 0x000002b7,
};
#define A_int_msg_sdtr3 0xab93000e
static u32 A_int_msg_sdtr3_used[] __attribute((unused)) = {
- 0x000002f1,
+ 0x00000303,
};
#define A_int_no_msgout1 0xab93000f
static u32 A_int_no_msgout1_used[] __attribute((unused)) = {
- 0x00000281,
+ 0x0000028b,
};
#define A_int_no_msgout2 0xab930010
static u32 A_int_no_msgout2_used[] __attribute((unused)) = {
- 0x000002c1,
+ 0x000002d7,
};
#define A_int_no_msgout3 0xab930011
static u32 A_int_no_msgout3_used[] __attribute((unused)) = {
- 0x00000301,
+ 0x00000323,
};
#define A_int_not_cmd_complete 0xab930012
static u32 A_int_not_cmd_complete_used[] __attribute((unused)) = {
- 0x00000031,
+ 0x0000002f,
};
#define A_int_not_rej 0xab93001c
static u32 A_int_not_rej_used[] __attribute((unused)) = {
- 0x0000030d,
+ 0x0000032f,
};
#define A_int_resel_not_msgin 0xab930016
static u32 A_int_resel_not_msgin_used[] __attribute((unused)) = {
- 0x00000317,
+ 0x00000339,
};
#define A_int_reselected 0xab930017
static u32 A_int_reselected_used[] __attribute((unused)) = {
- 0x0000031b,
+ 0x0000033d,
};
#define A_int_sel_no_ident 0xab930013
static u32 A_int_sel_no_ident_used[] __attribute((unused)) = {
- 0x0000000f,
+ 0x0000000d,
};
#define A_int_sel_not_cmd 0xab930014
static u32 A_int_sel_not_cmd_used[] __attribute((unused)) = {
- 0x00000019,
+ 0x00000017,
};
#define A_int_selected 0xab930018
static u32 A_int_selected_used[] __attribute((unused)) = {
- 0x0000032d,
+ 0x0000034f,
};
#define A_int_status_not_msgin 0xab930015
static u32 A_int_status_not_msgin_used[] __attribute((unused)) = {
- 0x0000002d,
+ 0x0000002b,
+};
+
+#define A_int_test1 0xab93001d
+static u32 A_int_test1_used[] __attribute((unused)) = {
+ 0x00000354,
+};
+
+#define A_msg_reject 0x00000000
+static u32 A_msg_reject_used[] __attribute((unused)) = {
+ 0x00000279,
+ 0x000002c5,
+ 0x00000311,
};
#define A_msgin_buf 0x00000000
static u32 A_msgin_buf_used[] __attribute((unused)) = {
- 0x0000024b,
- 0x0000025f,
- 0x00000267,
- 0x0000026f,
- 0x0000028b,
- 0x0000029f,
- 0x000002a7,
+ 0x00000249,
+ 0x0000025d,
+ 0x00000263,
+ 0x00000269,
+ 0x00000275,
+ 0x00000295,
+ 0x000002a9,
0x000002af,
- 0x000002cb,
- 0x000002df,
- 0x000002e7,
- 0x000002ef,
- 0x0000030b,
+ 0x000002b5,
+ 0x000002c1,
+ 0x000002e1,
+ 0x000002f5,
+ 0x000002fb,
+ 0x00000301,
+ 0x0000030d,
+ 0x0000032d,
};
#define A_reselected_identify 0x00000000
static u32 A_reselected_identify_used[] __attribute((unused)) = {
- 0x00000319,
+ 0x0000033b,
+};
+
+#define A_test1_dst 0x00000000
+static u32 A_test1_dst_used[] __attribute((unused)) = {
+ 0x00000352,
+};
+
+#define A_test1_src 0x00000000
+static u32 A_test1_src_used[] __attribute((unused)) = {
+ 0x00000351,
};
#define Ent_do_select 0x00000000
-#define Ent_done_ident 0x00000050
-#define Ent_end_data_trans 0x00000908
-#define Ent_patch_input_data 0x000000e8
-#define Ent_patch_new_dsa 0x00000c88
-#define Ent_patch_output_data 0x00000500
-#define Ent_reselect 0x00000c48
-#define Ent_resume_cmd 0x00000068
-#define Ent_resume_msgin1a 0x000009e0
-#define Ent_resume_msgin1b 0x000009f0
-#define Ent_resume_msgin2a 0x00000ae0
-#define Ent_resume_msgin2b 0x00000af0
-#define Ent_resume_msgin3a 0x00000be0
-#define Ent_resume_msgin3b 0x00000bf0
-#define Ent_resume_pmm 0x00000078
-#define Ent_resume_rej_ident 0x00000c20
-#define Ent_wait_disc1 0x000009d0
-#define Ent_wait_disc2 0x00000ad0
-#define Ent_wait_disc3 0x00000bd0
-#define Ent_wait_disc_complete 0x000000d0
+#define Ent_done_ident 0x00000048
+#define Ent_end_data_trans 0x00000900
+#define Ent_patch_input_data 0x000000e0
+#define Ent_patch_new_dsa 0x00000d10
+#define Ent_patch_output_data 0x000004f8
+#define Ent_reselect 0x00000cd0
+#define Ent_resume_cmd 0x00000060
+#define Ent_resume_msgin1a 0x00000a08
+#define Ent_resume_msgin1b 0x00000a18
+#define Ent_resume_msgin2a 0x00000b38
+#define Ent_resume_msgin2b 0x00000b48
+#define Ent_resume_msgin3a 0x00000c68
+#define Ent_resume_msgin3b 0x00000c78
+#define Ent_resume_pmm 0x00000070
+#define Ent_resume_rej_ident 0x00000ca8
+#define Ent_test1 0x00000d40
+#define Ent_wait_disc1 0x000009f8
+#define Ent_wait_disc2 0x00000b28
+#define Ent_wait_disc3 0x00000c58
+#define Ent_wait_disc_complete 0x000000c8
static u32 LABELPATCHES[] __attribute((unused)) = {
+ 0x00000005,
0x00000007,
- 0x00000009,
+ 0x00000013,
0x00000015,
- 0x00000017,
+ 0x0000001d,
0x0000001f,
0x00000021,
0x00000023,
- 0x00000025,
- 0x0000013d,
+ 0x0000013b,
+ 0x00000241,
0x00000243,
- 0x00000245,
+ 0x0000024b,
0x0000024d,
0x0000024f,
0x00000251,
- 0x00000253,
- 0x00000259,
- 0x00000261,
- 0x00000269,
+ 0x00000257,
+ 0x0000025f,
+ 0x00000265,
+ 0x00000273,
+ 0x00000277,
0x0000027b,
- 0x00000287,
- 0x0000028d,
- 0x0000028f,
+ 0x00000285,
0x00000291,
- 0x00000293,
+ 0x00000297,
0x00000299,
- 0x000002a1,
- 0x000002a9,
- 0x000002bb,
+ 0x0000029b,
+ 0x0000029d,
+ 0x000002a3,
+ 0x000002ab,
+ 0x000002b1,
+ 0x000002bf,
+ 0x000002c3,
0x000002c7,
- 0x000002cd,
- 0x000002cf,
0x000002d1,
- 0x000002d3,
- 0x000002d9,
- 0x000002e1,
+ 0x000002dd,
+ 0x000002e3,
+ 0x000002e5,
+ 0x000002e7,
0x000002e9,
- 0x000002fb,
- 0x00000307,
- 0x00000311,
- 0x00000315,
- 0x0000031f,
- 0x0000032b,
+ 0x000002ef,
+ 0x000002f7,
+ 0x000002fd,
+ 0x0000030b,
+ 0x0000030f,
+ 0x00000313,
+ 0x0000031d,
+ 0x00000329,
+ 0x00000333,
+ 0x00000337,
+ 0x00000341,
+ 0x0000034d,
};
static struct {
@@ -2356,6 +2447,6 @@
} EXTERNAL_PATCHES[] __attribute((unused)) = {
};
-static u32 INSTRUCTIONS __attribute((unused)) = 407;
-static u32 PATCHES __attribute((unused)) = 42;
+static u32 INSTRUCTIONS __attribute((unused)) = 426;
+static u32 PATCHES __attribute((unused)) = 51;
static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0;
diff -uaNr linux-2.4.21/fs/blkdev_swap.c linux-2.4.21-1APTUS/fs/blkdev_swap.c
--- linux-2.4.21/fs/blkdev_swap.c 1970-01-01 08:00:00.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/blkdev_swap.c 2003-06-23 01:55:01.000000000 +0800
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2000-2002 Shaolin Microsystems Ltd.
+ *
+ * Swapping to partitions or files on local disk partitions.
+ *
+ * David Chow <davidchow@shaolinmicro.com>
+ *
+ * Copied from the original fs/buffer.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/fs.h>
+
+#ifdef DEBUG_BLKDEV_SWAP
+# define dprintk(fmt...) printk(##fmt)
+#else
+# define dprintk(fmt...) do { /* */ } while (0)
+#endif
+
+#define BLKDEV_SWAP_ID "blockdev"
+#define BLKDEV_FILE_SWAP_ID "blockdev file"
+
+/*
+ * Helper function, copied here from buffer.c
+ */
+
+/*
+ * Start I/O on a page.
+ * This function expects the page to be locked and may return
+ * before I/O is complete. You then have to check page->locked,
+ * page->uptodate, and maybe wait on page->wait.
+ *
+ * brw_swap_page() is SMP-safe, although it's being called with the
+ * kernel lock held - but the code is ready.
+ *
+ * FIXME: we need a swapper_inode->get_block function to remove
+ * some of the bmap kludges and interface ugliness here.
+ */
+int brw_swap_page(int rw, struct page *page, kdev_t dev, int b[], int size)
+{
+ struct buffer_head *head, *bh;
+
+ if (!PageLocked(page))
+ panic("brw_swap_page: page not locked for I/O");
+
+ if (!page->buffers)
+ create_empty_buffers(page, dev, size);
+ head = bh = page->buffers;
+
+ /* Stage 1: lock all the buffers */
+ do {
+ lock_buffer(bh);
+ bh->b_blocknr = *(b++);
+ set_bit(BH_Mapped, &bh->b_state);
+ set_buffer_async_io(bh);
+ bh = bh->b_this_page;
+ } while (bh != head);
+
+ /* Stage 2: start the IO */
+ do {
+ struct buffer_head *next = bh->b_this_page;
+ submit_bh(rw, bh);
+ bh = next;
+ } while (bh != head);
+ return 0;
+}
+
+/*
+ * We implement to methods: swapping to partitions, and swapping to files
+ * located on partitions.
+ */
+
+struct blkdev_swap_data {
+ kdev_t dev;
+};
+
+struct test_data {
+ struct file * filp;
+ kdev_t dev;
+};
+
+static int is_blkdev_swapping(unsigned int flags,
+ struct file * swapf,
+ void *data)
+{
+ struct test_data *testdata = (struct test_data *) data;
+ struct file * filp = testdata->filp;
+ kdev_t dev = testdata->dev;
+
+ /* Only check filp's that don't match the one already opened
+ * for us by sys_swapon(). Otherwise, we will always flag a
+ * busy swap file.
+ */
+
+ if (swapf != filp) {
+ if (dev == swapf->f_dentry->d_inode->i_rdev)
+ return 1;
+ }
+ return 0;
+}
+
+static int blkdev_swap_open(struct file * filp, void **dptr)
+{
+ int swapfilesize;
+ kdev_t dev;
+ struct blkdev_swap_data *data;
+ int error;
+ struct test_data testdata;
+
+ MOD_INC_USE_COUNT;
+
+ if (!S_ISBLK(filp->f_dentry->d_inode->i_mode)) {
+ dprintk(__FUNCTION__": can't handle this swap file: %s\n",
+ swapf->d_name.name);
+ error = 0; /* not for us */
+ goto bad_swap;
+ }
+
+ dev = filp->f_dentry->d_inode->i_rdev;
+ set_blocksize(dev, PAGE_SIZE);
+ error = -ENODEV;
+ if (!dev ||
+ (blk_size[MAJOR(dev)] && !blk_size[MAJOR(dev)][MINOR(dev)])) {
+ printk("blkdev_swap_open: blkdev weirdness for %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ error = -EBUSY;
+ /* Check to see if the device is mounted */
+ if (S_ISBLK(filp->f_dentry->d_inode->i_mode) && is_mounted(dev)) {
+ printk("blkdev_swap_open: device already mounted, please unmount %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ /* Check to make sure that we aren't already swapping. */
+ testdata.filp = filp;
+ testdata.dev = dev;
+ if (swap_run_test(is_blkdev_swapping, &testdata)) {
+ printk("blkdev_swap_open: already swapping to %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ /* Check to make sure that we aren't already swapping. */
+ testdata.filp = filp;
+ testdata.dev = dev;
+ if (swap_run_test(is_blkdev_swapping, &testdata)) {
+ printk("blkdev_swap_open: already swapping to %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ swapfilesize = 0;
+ if (blk_size[MAJOR(dev)])
+ swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
+ >> (PAGE_SHIFT - 10);
+
+ if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
+ printk("blkdev_swap_open: can't allocate data for %s\n",
+ filp->f_dentry->d_name.name);
+ error = -ENOMEM;
+ goto bad_swap;
+ }
+ data->dev = dev;
+ *dptr = data;
+
+ dprintk("blkdev_swap_open: returning %d\n", swapfilesize);
+ return swapfilesize;
+
+ bad_swap:
+ MOD_DEC_USE_COUNT;
+ return error; /* this swap thing is not for us */
+}
+
+static int blkdev_swap_release(struct file * filp, void *data)
+{
+ dprintk("blkdev_swap_release: releasing swap device %s\n",
+ filp->f_dentry->d_name.name);
+ kfree(data);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int blkdev_rw_page(int rw, struct page *page, unsigned long offset,
+ void *ptr)
+{
+ struct blkdev_swap_data *data = (struct blkdev_swap_data *)ptr;
+ brw_swap_page(rw, page, data->dev, (int *)&offset, PAGE_SIZE);
+ return 1;
+}
+
+static struct swap_ops blkdev_swap_ops = {
+ blkdev_swap_open,
+ blkdev_swap_release,
+ blkdev_rw_page
+};
+
+struct blkdevfile_swap_data {
+ struct inode *swapf;
+};
+
+static int is_blkdevfile_swapping(unsigned int flags,
+ struct file * swapf,
+ void * data)
+{
+ struct file * filp = (struct file *) data;
+
+ /* Only check filp's that don't match the one already opened
+ * for us by sys_swapon(). Otherwise, we will always flag a
+ * busy swap file.
+ */
+
+ if (swapf != filp) {
+ if (filp->f_dentry->d_inode == swapf->f_dentry->d_inode)
+ return 1;
+ }
+ return 0;
+}
+
+static int blkdevfile_swap_open(struct file *swapf, void **dptr)
+{
+ int error = 0;
+ int swapfilesize;
+ struct blkdevfile_swap_data *data;
+
+ MOD_INC_USE_COUNT;
+
+ /* first check whether this is a regular file located on a local
+ * hard disk
+ */
+ if (!S_ISREG(swapf->f_dentry->d_inode->i_mode)) {
+ dprintk("blkdevfile_swap_open: "
+ "can't handle this swap file: %s\n",
+ swapf->d_name.name);
+ error = 0; /* not for us */
+ goto bad_swap;
+ }
+ if (!swapf->f_dentry->d_inode->i_mapping->a_ops->bmap) {
+ dprintk("blkdevfile_swap_open: no bmap for file: %s\n",
+ swapf->d_name.name);
+ error = 0; /* not for us */
+ goto bad_swap;
+ }
+
+ if (swap_run_test(is_blkdevfile_swapping, swapf)) {
+ dprintk("blkdevfile_swap_open: already swapping to %s\n",
+ swapf->d_name.name);
+ error = -EBUSY;
+ goto bad_swap;
+ }
+ swapfilesize = swapf->f_dentry->d_inode->i_size >> PAGE_SHIFT;
+ if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
+ error = -ENOMEM;
+ goto bad_swap;
+ }
+ data->swapf = swapf->f_dentry->d_inode;
+ *dptr = data;
+ return swapfilesize;
+
+ bad_swap:
+ MOD_DEC_USE_COUNT;
+ return error;
+}
+
+static int blkdevfile_swap_release(struct file *swapf, void *data)
+{
+ kfree(data);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int blkdevfile_rw_page(int rw, struct page *page, unsigned long offset,
+ void *ptr)
+{
+ struct blkdevfile_swap_data *data = (struct blkdevfile_swap_data *)ptr;
+ struct inode * swapf = data->swapf;
+ int i, j;
+ unsigned int block = offset
+ << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
+ kdev_t dev = swapf->i_dev;
+ int block_size;
+ int zones[PAGE_SIZE/512];
+ int zones_used;
+
+ block_size = swapf->i_sb->s_blocksize;
+ for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
+ if (!(zones[i] = bmap(swapf,block++))) {
+ printk("blkdevfile_rw_page: bad swap file\n");
+ return 0;
+ }
+ zones_used = i;
+
+ /* block_size == PAGE_SIZE/zones_used */
+ brw_swap_page(rw, page, dev, zones, block_size);
+ return 1;
+}
+
+static struct swap_ops blkdevfile_swap_ops = {
+ blkdevfile_swap_open,
+ blkdevfile_swap_release,
+ blkdevfile_rw_page
+ };
+
+int __init blkdev_swap_init(void)
+{
+ (void)register_swap_method(BLKDEV_SWAP_ID, &blkdev_swap_ops);
+ (void)register_swap_method(BLKDEV_FILE_SWAP_ID, &blkdevfile_swap_ops);
+ return 0;
+}
+
+void __exit blkdev_swap_exit(void)
+{
+ unregister_swap_method(BLKDEV_SWAP_ID);
+ unregister_swap_method(BLKDEV_FILE_SWAP_ID);
+}
+
+module_init(blkdev_swap_init)
+module_exit(blkdev_swap_exit)
diff -uaNr linux-2.4.21/fs/buffer.c linux-2.4.21-1APTUS/fs/buffer.c
--- linux-2.4.21/fs/buffer.c 2003-06-22 17:35:00.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/buffer.c 2003-06-23 01:57:44.000000000 +0800
@@ -737,7 +737,7 @@
bh->b_private = private;
}
-static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
+void end_buffer_io_async(struct buffer_head * bh, int uptodate)
{
static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
diff -uaNr linux-2.4.21/fs/Config.in linux-2.4.21-1APTUS/fs/Config.in
--- linux-2.4.21/fs/Config.in 2002-11-29 07:53:15.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/Config.in 2003-06-23 11:08:34.000000000 +0800
@@ -4,6 +4,8 @@
mainmenu_option next_comment
comment 'File systems'
+tristate 'Swapping to block devices and local filesystems' CONFIG_BLOCKDEV_SWAP
+
bool 'Quota support' CONFIG_QUOTA
tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
diff -uaNr linux-2.4.21/fs/Makefile linux-2.4.21-1APTUS/fs/Makefile
--- linux-2.4.21/fs/Makefile 2002-11-29 07:53:15.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/Makefile 2003-06-22 19:53:12.000000000 +0800
@@ -82,5 +82,6 @@
# persistent filesystems
obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
+obj-$(CONFIG_BLOCKDEV_SWAP) += blkdev_swap.o
include $(TOPDIR)/Rules.make
diff -uaNr linux-2.4.21/include/linux/fs.h linux-2.4.21-1APTUS/include/linux/fs.h
--- linux-2.4.21/include/linux/fs.h 2003-06-22 17:35:06.000000000 +0800
+++ linux-2.4.21-1APTUS/include/linux/fs.h 2003-06-23 01:15:04.000000000 +0800
@@ -1128,6 +1128,7 @@
extern void refile_buffer(struct buffer_head * buf);
extern void create_empty_buffers(struct page *, kdev_t, unsigned long);
extern void end_buffer_io_sync(struct buffer_head *bh, int uptodate);
+extern void end_buffer_io_async(struct buffer_head * bh, int uptodate);
/* reiserfs_writepage needs this */
extern void set_buffer_async_io(struct buffer_head *bh) ;
diff -uaNr linux-2.4.21/include/linux/swap.h linux-2.4.21-1APTUS/include/linux/swap.h
--- linux-2.4.21/include/linux/swap.h 2003-06-22 17:35:07.000000000 +0800
+++ linux-2.4.21-1APTUS/include/linux/swap.h 2003-06-23 01:38:41.000000000 +0800
@@ -58,15 +58,29 @@
#define SWAP_MAP_MAX 0x7fff
#define SWAP_MAP_BAD 0x8000
+struct swap_ops {
+ int (*open)(struct file *swapf, void **data);
+ int (*release)(struct file *swapf, void *data);
+ int (*rw_page)(int rw,
+ struct page *page, unsigned long offset, void *data);
+};
+
+struct swap_method {
+ struct swap_method *next;
+ char * name;
+ struct swap_ops *ops;
+ int use_count;
+};
+
/*
* The in-memory structure used to track swap areas.
*/
struct swap_info_struct {
unsigned int flags;
- kdev_t swap_device;
+ struct file *swap_file;
+ struct swap_method *method;
+ void *data;
spinlock_t sdev_lock;
- struct dentry * swap_file;
- struct vfsmount *swap_vfsmnt;
unsigned short * swap_map;
unsigned int lowest_bit;
unsigned int highest_bit;
@@ -142,10 +156,15 @@
extern unsigned int nr_swapfiles;
extern struct swap_info_struct swap_info[];
extern int is_swap_partition(kdev_t);
+extern int register_swap_method(char *name, struct swap_ops *ops);
+extern int unregister_swap_method(char *name);
+extern int swap_run_test(int (*test_fct)(unsigned int flags,
+ struct file *swap_file,
+ void *testdata), void *testdata);
extern void si_swapinfo(struct sysinfo *);
extern swp_entry_t get_swap_page(void);
-extern void get_swaphandle_info(swp_entry_t, unsigned long *, kdev_t *,
- struct inode **);
+struct swap_method *get_swaphandle_info(swp_entry_t entry,
+ unsigned long *offset, void **data);
extern int swap_duplicate(swp_entry_t);
extern int valid_swaphandles(swp_entry_t, unsigned long *);
extern void swap_free(swp_entry_t);
diff -uaNr linux-2.4.21/kernel/ksyms.c linux-2.4.21-1APTUS/kernel/ksyms.c
--- linux-2.4.21/kernel/ksyms.c 2003-06-22 18:34:45.000000000 +0800
+++ linux-2.4.21-1APTUS/kernel/ksyms.c 2003-06-23 01:02:29.000000000 +0800
@@ -41,6 +41,7 @@
#include <linux/mm.h>
#include <linux/capability.h>
#include <linux/highuid.h>
+#include <linux/swapctl.h>
#include <linux/brlock.h>
#include <linux/fs.h>
#include <linux/tty.h>
@@ -93,6 +94,10 @@
EXPORT_SYMBOL(kallsyms_symbol_to_address);
EXPORT_SYMBOL(kallsyms_address_to_symbol);
#endif
+EXPORT_SYMBOL(nr_free_pages);
+EXPORT_SYMBOL(register_swap_method);
+EXPORT_SYMBOL(unregister_swap_method);
+EXPORT_SYMBOL(swap_run_test);
/* process memory management */
EXPORT_SYMBOL(do_mmap_pgoff);
diff -uaNr linux-2.4.21/mm/page_io.c linux-2.4.21-1APTUS/mm/page_io.c
--- linux-2.4.21/mm/page_io.c 2002-11-29 07:53:15.000000000 +0800
+++ linux-2.4.21-1APTUS/mm/page_io.c 2003-06-23 00:32:31.000000000 +0800
@@ -32,15 +32,15 @@
* atomic, which is particularly important when we are trying to ensure
* that shared pages stay shared while being swapped.
*/
-
+/* David: Don't know is this is corrct or not, since 2.4.14, the rw never
+ * checked for WRITE. Not sure will we cause a problem here if we check for
+ * WRITE and start I/O and wait for completion.
+ */
static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
{
unsigned long offset;
- int zones[PAGE_SIZE/512];
- int zones_used;
- kdev_t dev = 0;
- int block_size;
- struct inode *swapf = 0;
+ struct swap_method *method;
+ void *data;
if (rw == READ) {
ClearPageUptodate(page);
@@ -48,31 +48,21 @@
} else
kstat.pswpout++;
- get_swaphandle_info(entry, &offset, &dev, &swapf);
- if (dev) {
- zones[0] = offset;
- zones_used = 1;
- block_size = PAGE_SIZE;
- } else if (swapf) {
- int i, j;
- unsigned int block = offset
- << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
-
- block_size = swapf->i_sb->s_blocksize;
- for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
- if (!(zones[i] = bmap(swapf,block++))) {
- printk("rw_swap_page: bad swap file\n");
- return 0;
- }
- zones_used = i;
- dev = swapf->i_dev;
- } else {
- return 0;
+ method = get_swaphandle_info(entry, &offset, &data);
+
+ if (method) {
+ if (!method->ops->rw_page(rw, page, offset, data)) {
+ return 0;
+ }
+ /* Note! For consistency we do all of the logic,
+ * decrementing the page count, and unlocking the page in the
+ * swap lock map - in the IO completion handler.
+ */
+ return 1;
+
}
- /* block_size == PAGE_SIZE/zones_used */
- brw_page(rw, page, dev, zones, block_size);
- return 1;
+ return 0;
}
/*
diff -uaNr linux-2.4.21/mm/swapfile.c linux-2.4.21-1APTUS/mm/swapfile.c
--- linux-2.4.21/mm/swapfile.c 2003-06-22 17:35:08.000000000 +0800
+++ linux-2.4.21-1APTUS/mm/swapfile.c 2003-06-23 11:09:17.000000000 +0800
@@ -14,9 +14,15 @@
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/shm.h>
-
+#include <linux/file.h>
+#include <linux/compiler.h>
+#include <linux/nfs_fs.h>
#include <asm/pgtable.h>
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
spinlock_t swaplock = SPIN_LOCK_UNLOCKED;
unsigned int nr_swapfiles;
int total_swap_pages;
@@ -31,8 +37,78 @@
struct swap_info_struct swap_info[MAX_SWAPFILES];
+static struct swap_method *swap_methods = NULL;
+
#define SWAPFILE_CLUSTER 256
+int register_swap_method(char *name, struct swap_ops *ops)
+{
+ struct swap_method *pos;
+ struct swap_method *new;
+ int result = 0;
+
+ lock_kernel();
+
+ for (pos = swap_methods; pos; pos = pos->next) {
+ if (strcmp(pos->name, name) == 0) {
+ printk(KERN_ERR "register_swap_method: "
+ "method %s already registered\n", name);
+ result = -EBUSY;
+ goto out;
+ }
+ }
+
+ if (!(new = kmalloc(sizeof(*new), GFP_KERNEL))) {
+ printk(KERN_ERR "register_swap_method: "
+ "no memory for new method \"%s\"\n", name);
+ result = -ENOMEM;
+ goto out;
+ }
+
+ new->name = name;
+ new->ops = ops;
+ new->use_count = 0;
+
+ /* ok, insert at top of list */
+ printk("register_swap_method: method %s\n", name);
+ new->next = swap_methods;
+ swap_methods = new;
+ out:
+ unlock_kernel();
+ return result;
+}
+
+int unregister_swap_method(char *name)
+{
+ struct swap_method **method, *next;
+ int result = 0;
+
+ lock_kernel();
+
+ for (method = &swap_methods; *method; method = &(*method)->next) {
+ if (strcmp((*method)->name, name) == 0) {
+ if ((*method)->use_count > 0) {
+ printk(KERN_ERR "unregister_swap_method: "
+ "method \"%s\" is in use\n", name);
+ result = -EBUSY;
+ goto out;
+ }
+
+ next = (*method)->next;
+ kfree(*method);
+ *method = next;
+ printk("unregister_swap_method: method %s\n", name);
+ goto out;
+ }
+ }
+ /* not found */
+ printk("unregister_swap_method: no such method %s\n", name);
+ result = -ENOENT;
+ out:
+ unlock_kernel();
+ return result;
+}
+
static inline int scan_swap_map(struct swap_info_struct *si)
{
unsigned long offset;
@@ -717,7 +793,7 @@
err = user_path_walk(specialfile, &nd);
if (err)
- goto out;
+ return err;
lock_kernel();
prev = -1;
@@ -725,15 +801,20 @@
for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
p = swap_info + type;
if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
- if (p->swap_file == nd.dentry)
- break;
+ if (p->swap_file &&
+ p->swap_file->f_dentry == nd.dentry)
+ break;
}
prev = type;
}
err = -EINVAL;
+ /* p->swap_file contains all needed info, no need to keep nd, so
+ * release it now.
+ */
+ path_release(&nd);
if (type < 0) {
swap_list_unlock();
- goto out_dput;
+ goto out;
}
if (prev < 0) {
@@ -767,19 +848,18 @@
total_swap_pages += p->pages;
p->flags = SWP_WRITEOK;
swap_list_unlock();
- goto out_dput;
+ goto out;
}
- if (p->swap_device)
- blkdev_put(p->swap_file->d_inode->i_bdev, BDEV_SWAP);
- path_release(&nd);
+ if (p->method->ops->release)
+ p->method->ops->release(p->swap_file, p->data);
swap_list_lock();
swap_device_lock(p);
- nd.mnt = p->swap_vfsmnt;
- nd.dentry = p->swap_file;
- p->swap_vfsmnt = NULL;
+ p->method->use_count --;
+ p->method = NULL;
+ p->data = NULL;
+ filp_close(p->swap_file, NULL);
p->swap_file = NULL;
- p->swap_device = 0;
p->max = 0;
swap_map = p->swap_map;
p->swap_map = NULL;
@@ -789,10 +869,8 @@
vfree(swap_map);
err = 0;
-out_dput:
- unlock_kernel();
- path_release(&nd);
out:
+ unlock_kernel();
return err;
}
@@ -805,18 +883,17 @@
if (!page)
return -ENOMEM;
- len += sprintf(buf, "Filename\t\t\tType\t\tSize\tUsed\tPriority\n");
+ len += sprintf(buf, "%-32s%-16s%-8s%-8sPriority\n",
+ "Filename", "Type", "Size", "Used");
for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
if ((ptr->flags & SWP_USED) && ptr->swap_map) {
- char * path = d_path(ptr->swap_file, ptr->swap_vfsmnt,
- page, PAGE_SIZE);
+ char * path = d_path(ptr->swap_file->f_dentry,
+ ptr->swap_file->f_vfsmnt,
+ page, PAGE_SIZE);
len += sprintf(buf + len, "%-31s ", path);
- if (!ptr->swap_device)
- len += sprintf(buf + len, "file\t\t");
- else
- len += sprintf(buf + len, "partition\t");
+ len += sprintf(buf + len, "%-15s ", ptr->method->name);
usedswap = 0;
for (j = 0; j < ptr->max; ++j)
@@ -827,7 +904,7 @@
default:
usedswap++;
}
- len += sprintf(buf + len, "%d\t%d\t%d\n", ptr->pages << (PAGE_SHIFT - 10),
+ len += sprintf(buf + len, "%-8d%-8d%d\n", ptr->pages << (PAGE_SHIFT - 10),
usedswap << (PAGE_SHIFT - 10), ptr->prio);
}
}
@@ -835,28 +912,89 @@
return len;
}
-int is_swap_partition(kdev_t dev) {
+/* apply a test function to all active swap objects. E.g. for checking
+ * whether a partition is used for swapping
+ */
+int swap_run_test(int (*test_fct)(unsigned int flags,
+ struct file * swap_file,
+ void *testdata), void *testdata)
+{
struct swap_info_struct *ptr = swap_info;
int i;
for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
- if (ptr->flags & SWP_USED)
- if (ptr->swap_device == dev)
- return 1;
+ if (ptr->swap_file &&
+ test_fct(ptr->flags, ptr->swap_file, testdata))
+ return 1;
}
return 0;
}
+/* Walk through the list of known swap method until somebody wants to
+ * handle this file. Pick the first one which claims to be able to
+ * swap to this kind of file.
+ *
+ * return value: < 0: error, 0: not found, > 0: swapfilesize
+ */
+int find_swap_method(struct file *swap_file,
+ struct swap_info_struct *p)
+{
+ int swapfilesize = 0;
+ struct swap_method *method;
+
+ p->method = NULL;
+ for (method = swap_methods; method; method = method->next) {
+ swapfilesize = method->ops->open(swap_file, &p->data);
+ if (swapfilesize == 0) {
+ continue;
+ }
+ if (swapfilesize > 0) {
+ p->method = method;
+ p->method->use_count ++;
+ p->swap_file = swap_file;
+ break;
+ }
+ if (swapfilesize < 0) {
+ break;
+ }
+ }
+ return swapfilesize;
+}
+
+/* swap_run_test() applies this hook to all swapfiles until it returns
+ * "1". If it never return "1", the result of swap_run_test() is "0",
+ * otherwise "1".
+ */
+static int is_swap_partition_hook(unsigned int flags, struct file *swap_file,
+ void *testdata)
+{
+ kdev_t swap_dev = S_ISBLK(swap_file->f_dentry->d_inode->i_mode)
+ ? swap_file->f_dentry->d_inode->i_rdev : 0;
+ kdev_t dev = *((kdev_t *)testdata);
+
+ if (flags & SWP_USED && dev == swap_dev) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* A wrapper to the swap_run_test() which test for swap methods
+ */
+int is_swap_partition(kdev_t dev) {
+ return swap_run_test(is_swap_partition_hook, &dev);
+}
+
/*
* Written 01/25/92 by Simmule Turner, heavily changed by Linus.
+ * 22nd June 2003 David Chow <davidchow@shaolinmicro.com>
+ * Modified to enable the swap method hooks
*
* The swapon system call
*/
asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
{
struct swap_info_struct * p;
- struct nameidata nd;
- struct inode * swap_inode;
unsigned int type;
int i, j, prev;
int error;
@@ -866,9 +1004,9 @@
int nr_good_pages = 0;
unsigned long maxpages = 1;
int swapfilesize;
- struct block_device *bdev = NULL;
unsigned short *swap_map;
-
+ char * tmp_specialfile;
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
lock_kernel();
@@ -886,8 +1024,7 @@
nr_swapfiles = type+1;
p->flags = SWP_USED;
p->swap_file = NULL;
- p->swap_vfsmnt = NULL;
- p->swap_device = 0;
+ p->method = NULL;
p->swap_map = NULL;
p->lowest_bit = 0;
p->highest_bit = 0;
@@ -901,58 +1038,69 @@
p->prio = --least_priority;
}
swap_list_unlock();
- error = user_path_walk(specialfile, &nd);
- if (error)
- goto bad_swap_2;
-
- p->swap_file = nd.dentry;
- p->swap_vfsmnt = nd.mnt;
- swap_inode = nd.dentry->d_inode;
- error = -EINVAL;
+ /* Open the swap using filp_open. Bail out on any errors. */
+ tmp_specialfile = getname(specialfile);
+ if (IS_ERR(tmp_specialfile)) {
+ error = PTR_ERR(tmp_specialfile);
+ goto bad_swap_2;
+ }
+ p->swap_file = filp_open(tmp_specialfile, O_RDWR, 0600);
+ putname(tmp_specialfile);
+ if (IS_ERR(p->swap_file)) {
+ error = PTR_ERR(p->swap_file);
+ goto bad_swap_1;
+ }
- if (S_ISBLK(swap_inode->i_mode)) {
- kdev_t dev = swap_inode->i_rdev;
- struct block_device_operations *bdops;
- devfs_handle_t de;
-
- if (is_mounted(dev)) {
- error = -EBUSY;
- goto bad_swap_2;
- }
+ error = -EINVAL;
- p->swap_device = dev;
- set_blocksize(dev, PAGE_SIZE);
-
- bd_acquire(swap_inode);
- bdev = swap_inode->i_bdev;
- de = devfs_get_handle_from_inode(swap_inode);
- bdops = devfs_get_ops(de); /* Increments module use count */
- if (bdops) bdev->bd_op = bdops;
-
- error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_SWAP);
- devfs_put_ops(de);/*Decrement module use count now we're safe*/
- if (error)
- goto bad_swap_2;
- set_blocksize(dev, PAGE_SIZE);
- error = -ENODEV;
- if (!dev || (blk_size[MAJOR(dev)] &&
- !blk_size[MAJOR(dev)][MINOR(dev)]))
- goto bad_swap;
- swapfilesize = 0;
- if (blk_size[MAJOR(dev)])
- swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
- >> (PAGE_SHIFT - 10);
- } else if (S_ISREG(swap_inode->i_mode))
- swapfilesize = swap_inode->i_size >> PAGE_SHIFT;
- else
- goto bad_swap;
+ swapfilesize = find_swap_method(p->swap_file, p);
+ if (swapfilesize < 0) {
+ error = swapfilesize;
+ filp_close(p->swap_file, NULL);
+ goto bad_swap_1;
+ }
+
+#ifdef CONFIG_KMOD
+ if (swapfilesize == 0) {
+ if ((p->swap_file->f_dentry->d_sb
+ && (p->swap_file->f_dentry->d_sb->s_type->fs_flags & FS_REQUIRES_DEV))
+ || (p->swap_file->f_dentry->d_inode
+ && S_ISBLK(p->swap_file->f_dentry->d_inode->i_mode))) {
+ /* It looks like a block device filesystem */
+ (void)request_module("blkdev_swap");
+ } else {
+ /* User may specify which swap module it use */
+ (void)request_module("swapfile-mod");
+ }
+
+ swapfilesize = find_swap_method(p->swap_file, p);
+ if (swapfilesize < 0) {
+ error = swapfilesize;
+ filp_close(p->swap_file, NULL);
+ goto bad_swap_1;
+ }
+ }
+#endif
+ if (swapfilesize == 0) {
+ printk("Invalid swap file\n");
+ filp_close(p->swap_file, NULL);
+ goto bad_swap_1; /* free swap map */
+ }
+
+ /* After this point, the swap-file has been opened by the swap
+ * method. We must make sure to use the bad_swap label for any
+ * errors.
+ */
error = -EBUSY;
+
for (i = 0 ; i < nr_swapfiles ; i++) {
struct swap_info_struct *q = &swap_info[i];
if (i == type || !q->swap_file)
continue;
- if (swap_inode->i_mapping == q->swap_file->d_inode->i_mapping)
+ if (p->swap_file->f_dentry->d_inode->i_mapping
+ ==
+ q->swap_file->f_dentry->d_inode->i_mapping)
goto bad_swap;
}
@@ -1088,17 +1236,25 @@
swap_list_unlock();
error = 0;
goto out;
+
bad_swap:
- if (bdev)
- blkdev_put(bdev, BDEV_SWAP);
+ if (p->method->ops->release)
+ p->method->ops->release(p->swap_file, p->data);
+ swap_list_lock();
+ p->method->use_count --;
+ p->method = NULL;
+ p->data = NULL;
+ swap_list_unlock();
+
+bad_swap_1:
+ swap_list_lock();
+ p->swap_file = NULL;
+ swap_list_unlock();
+
bad_swap_2:
+
swap_list_lock();
swap_map = p->swap_map;
- nd.mnt = p->swap_vfsmnt;
- nd.dentry = p->swap_file;
- p->swap_device = 0;
- p->swap_file = NULL;
- p->swap_vfsmnt = NULL;
p->swap_map = NULL;
p->flags = 0;
if (!(swap_flags & SWAP_FLAG_PREFER))
@@ -1106,7 +1262,7 @@
swap_list_unlock();
if (swap_map)
vfree(swap_map);
- path_release(&nd);
+
out:
if (swap_header)
free_page((long) swap_header);
@@ -1181,8 +1337,8 @@
/*
* Prior swap_duplicate protects against swap device deletion.
*/
-void get_swaphandle_info(swp_entry_t entry, unsigned long *offset,
- kdev_t *dev, struct inode **swapf)
+struct swap_method *get_swaphandle_info(swp_entry_t entry,
+ unsigned long *offset, void **data)
{
unsigned long type;
struct swap_info_struct *p;
@@ -1190,32 +1346,26 @@
type = SWP_TYPE(entry);
if (type >= nr_swapfiles) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_file, entry.val);
- return;
+ return NULL;
}
p = &swap_info[type];
*offset = SWP_OFFSET(entry);
if (*offset >= p->max && *offset != 0) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_offset, entry.val);
- return;
+ return NULL;
}
if (p->swap_map && !p->swap_map[*offset]) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_offset, entry.val);
- return;
+ return NULL;
}
if (!(p->flags & SWP_USED)) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_file, entry.val);
- return;
+ return NULL;
}
- if (p->swap_device) {
- *dev = p->swap_device;
- } else if (p->swap_file) {
- *swapf = p->swap_file->d_inode;
- } else {
- printk(KERN_ERR "rw_swap_page: no swap file or device\n");
- }
- return;
+ *data = p->data;
+ return p->method;
}
/*
^ permalink raw reply [flat|nested] 2+ messages in thread
* (corrected) swap modules
2003-06-23 15:04 swap modules David Chow
@ 2003-06-23 15:51 ` David Chow
0 siblings, 0 replies; 2+ messages in thread
From: David Chow @ 2003-06-23 15:51 UTC (permalink / raw)
To: linux-mm
[-- Attachment #1: Type: text/plain, Size: 1164 bytes --]
Please ignore the previous patch, the file drivers/scsi/sim710_d.h was
accidentally patched. This is the correct one instead.
regards,
David Chow
David Chow wrote:
> Dear linux-mm team,
>
> This patch is for patching the mm and fs stuff to make the Linux
> 2.4.21 swap code to allow a concept of modularized swap methods. This
> concept and swap code is originally from Justus Heine who created the
> NFS swap patch for 2.2 and 2.4 . I've extracted the code and modified
> to make it as a generic swap module code. The vanilla kernel swap code
> is been moved to a file fs/blkdev_swap.c which is for normal plain
> block device swaps. Users can configure the kernel to include the
> local block device swap code or compile it as a module. Developers can
> also develop their own swap methods instead of using the plain swap
> code (may be some crypto for security reasons) . I've been using this
> API to develop NFS swap and netswap code for a year an more. This
> patch has been tested for more than a year in a production environment
> on smp and non-smp (I think it is quite stable though). Please find it
> useful.
>
> regards,
> David Chow
[-- Attachment #2: swap_module-2.4.21.diff --]
[-- Type: text/plain, Size: 29409 bytes --]
diff -uaNr linux-2.4.21/Documentation/Configure.help linux-2.4.21-1APTUS/Documentation/Configure.help
--- linux-2.4.21/Documentation/Configure.help 2003-06-22 18:34:45.000000000 +0800
+++ linux-2.4.21-1APTUS/Documentation/Configure.help 2003-06-22 19:57:04.000000000 +0800
@@ -12784,6 +12784,16 @@
If you are running Linux on an IBM iSeries system and you want to
read a CD drive owned by OS/400, say Y here.
+Swapping to block device and local filesystems
+CONFIG_BLOCKDEV_SWAP
+ Say yes to enable virtual memory swap to block devices. If you have
+ a local disk drive and wish to use swap say 'Y', otherwise say 'N'.
+
+ If local swaping is option to your system, say 'M' and compile it
+ as a module.
+
+ If unsure, choose 'M' to compile it as a module for safe.
+
Quota support
CONFIG_QUOTA
If you say Y here, you will be able to set per user limits for disk
diff -uaNr linux-2.4.21/fs/blkdev_swap.c linux-2.4.21-1APTUS/fs/blkdev_swap.c
--- linux-2.4.21/fs/blkdev_swap.c 1970-01-01 08:00:00.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/blkdev_swap.c 2003-06-23 01:55:01.000000000 +0800
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2000-2002 Shaolin Microsystems Ltd.
+ *
+ * Swapping to partitions or files on local disk partitions.
+ *
+ * David Chow <davidchow@shaolinmicro.com>
+ *
+ * Copied from the original fs/buffer.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/fs.h>
+
+#ifdef DEBUG_BLKDEV_SWAP
+# define dprintk(fmt...) printk(##fmt)
+#else
+# define dprintk(fmt...) do { /* */ } while (0)
+#endif
+
+#define BLKDEV_SWAP_ID "blockdev"
+#define BLKDEV_FILE_SWAP_ID "blockdev file"
+
+/*
+ * Helper function, copied here from buffer.c
+ */
+
+/*
+ * Start I/O on a page.
+ * This function expects the page to be locked and may return
+ * before I/O is complete. You then have to check page->locked,
+ * page->uptodate, and maybe wait on page->wait.
+ *
+ * brw_swap_page() is SMP-safe, although it's being called with the
+ * kernel lock held - but the code is ready.
+ *
+ * FIXME: we need a swapper_inode->get_block function to remove
+ * some of the bmap kludges and interface ugliness here.
+ */
+int brw_swap_page(int rw, struct page *page, kdev_t dev, int b[], int size)
+{
+ struct buffer_head *head, *bh;
+
+ if (!PageLocked(page))
+ panic("brw_swap_page: page not locked for I/O");
+
+ if (!page->buffers)
+ create_empty_buffers(page, dev, size);
+ head = bh = page->buffers;
+
+ /* Stage 1: lock all the buffers */
+ do {
+ lock_buffer(bh);
+ bh->b_blocknr = *(b++);
+ set_bit(BH_Mapped, &bh->b_state);
+ set_buffer_async_io(bh);
+ bh = bh->b_this_page;
+ } while (bh != head);
+
+ /* Stage 2: start the IO */
+ do {
+ struct buffer_head *next = bh->b_this_page;
+ submit_bh(rw, bh);
+ bh = next;
+ } while (bh != head);
+ return 0;
+}
+
+/*
+ * We implement to methods: swapping to partitions, and swapping to files
+ * located on partitions.
+ */
+
+struct blkdev_swap_data {
+ kdev_t dev;
+};
+
+struct test_data {
+ struct file * filp;
+ kdev_t dev;
+};
+
+static int is_blkdev_swapping(unsigned int flags,
+ struct file * swapf,
+ void *data)
+{
+ struct test_data *testdata = (struct test_data *) data;
+ struct file * filp = testdata->filp;
+ kdev_t dev = testdata->dev;
+
+ /* Only check filp's that don't match the one already opened
+ * for us by sys_swapon(). Otherwise, we will always flag a
+ * busy swap file.
+ */
+
+ if (swapf != filp) {
+ if (dev == swapf->f_dentry->d_inode->i_rdev)
+ return 1;
+ }
+ return 0;
+}
+
+static int blkdev_swap_open(struct file * filp, void **dptr)
+{
+ int swapfilesize;
+ kdev_t dev;
+ struct blkdev_swap_data *data;
+ int error;
+ struct test_data testdata;
+
+ MOD_INC_USE_COUNT;
+
+ if (!S_ISBLK(filp->f_dentry->d_inode->i_mode)) {
+ dprintk(__FUNCTION__": can't handle this swap file: %s\n",
+ swapf->d_name.name);
+ error = 0; /* not for us */
+ goto bad_swap;
+ }
+
+ dev = filp->f_dentry->d_inode->i_rdev;
+ set_blocksize(dev, PAGE_SIZE);
+ error = -ENODEV;
+ if (!dev ||
+ (blk_size[MAJOR(dev)] && !blk_size[MAJOR(dev)][MINOR(dev)])) {
+ printk("blkdev_swap_open: blkdev weirdness for %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ error = -EBUSY;
+ /* Check to see if the device is mounted */
+ if (S_ISBLK(filp->f_dentry->d_inode->i_mode) && is_mounted(dev)) {
+ printk("blkdev_swap_open: device already mounted, please unmount %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ /* Check to make sure that we aren't already swapping. */
+ testdata.filp = filp;
+ testdata.dev = dev;
+ if (swap_run_test(is_blkdev_swapping, &testdata)) {
+ printk("blkdev_swap_open: already swapping to %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ /* Check to make sure that we aren't already swapping. */
+ testdata.filp = filp;
+ testdata.dev = dev;
+ if (swap_run_test(is_blkdev_swapping, &testdata)) {
+ printk("blkdev_swap_open: already swapping to %s\n",
+ filp->f_dentry->d_name.name);
+ goto bad_swap;
+ }
+
+ swapfilesize = 0;
+ if (blk_size[MAJOR(dev)])
+ swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
+ >> (PAGE_SHIFT - 10);
+
+ if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
+ printk("blkdev_swap_open: can't allocate data for %s\n",
+ filp->f_dentry->d_name.name);
+ error = -ENOMEM;
+ goto bad_swap;
+ }
+ data->dev = dev;
+ *dptr = data;
+
+ dprintk("blkdev_swap_open: returning %d\n", swapfilesize);
+ return swapfilesize;
+
+ bad_swap:
+ MOD_DEC_USE_COUNT;
+ return error; /* this swap thing is not for us */
+}
+
+static int blkdev_swap_release(struct file * filp, void *data)
+{
+ dprintk("blkdev_swap_release: releasing swap device %s\n",
+ filp->f_dentry->d_name.name);
+ kfree(data);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int blkdev_rw_page(int rw, struct page *page, unsigned long offset,
+ void *ptr)
+{
+ struct blkdev_swap_data *data = (struct blkdev_swap_data *)ptr;
+ brw_swap_page(rw, page, data->dev, (int *)&offset, PAGE_SIZE);
+ return 1;
+}
+
+static struct swap_ops blkdev_swap_ops = {
+ blkdev_swap_open,
+ blkdev_swap_release,
+ blkdev_rw_page
+};
+
+struct blkdevfile_swap_data {
+ struct inode *swapf;
+};
+
+static int is_blkdevfile_swapping(unsigned int flags,
+ struct file * swapf,
+ void * data)
+{
+ struct file * filp = (struct file *) data;
+
+ /* Only check filp's that don't match the one already opened
+ * for us by sys_swapon(). Otherwise, we will always flag a
+ * busy swap file.
+ */
+
+ if (swapf != filp) {
+ if (filp->f_dentry->d_inode == swapf->f_dentry->d_inode)
+ return 1;
+ }
+ return 0;
+}
+
+static int blkdevfile_swap_open(struct file *swapf, void **dptr)
+{
+ int error = 0;
+ int swapfilesize;
+ struct blkdevfile_swap_data *data;
+
+ MOD_INC_USE_COUNT;
+
+ /* first check whether this is a regular file located on a local
+ * hard disk
+ */
+ if (!S_ISREG(swapf->f_dentry->d_inode->i_mode)) {
+ dprintk("blkdevfile_swap_open: "
+ "can't handle this swap file: %s\n",
+ swapf->d_name.name);
+ error = 0; /* not for us */
+ goto bad_swap;
+ }
+ if (!swapf->f_dentry->d_inode->i_mapping->a_ops->bmap) {
+ dprintk("blkdevfile_swap_open: no bmap for file: %s\n",
+ swapf->d_name.name);
+ error = 0; /* not for us */
+ goto bad_swap;
+ }
+
+ if (swap_run_test(is_blkdevfile_swapping, swapf)) {
+ dprintk("blkdevfile_swap_open: already swapping to %s\n",
+ swapf->d_name.name);
+ error = -EBUSY;
+ goto bad_swap;
+ }
+ swapfilesize = swapf->f_dentry->d_inode->i_size >> PAGE_SHIFT;
+ if ((data = kmalloc(sizeof(*data), GFP_KERNEL)) == NULL) {
+ error = -ENOMEM;
+ goto bad_swap;
+ }
+ data->swapf = swapf->f_dentry->d_inode;
+ *dptr = data;
+ return swapfilesize;
+
+ bad_swap:
+ MOD_DEC_USE_COUNT;
+ return error;
+}
+
+static int blkdevfile_swap_release(struct file *swapf, void *data)
+{
+ kfree(data);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int blkdevfile_rw_page(int rw, struct page *page, unsigned long offset,
+ void *ptr)
+{
+ struct blkdevfile_swap_data *data = (struct blkdevfile_swap_data *)ptr;
+ struct inode * swapf = data->swapf;
+ int i, j;
+ unsigned int block = offset
+ << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
+ kdev_t dev = swapf->i_dev;
+ int block_size;
+ int zones[PAGE_SIZE/512];
+ int zones_used;
+
+ block_size = swapf->i_sb->s_blocksize;
+ for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
+ if (!(zones[i] = bmap(swapf,block++))) {
+ printk("blkdevfile_rw_page: bad swap file\n");
+ return 0;
+ }
+ zones_used = i;
+
+ /* block_size == PAGE_SIZE/zones_used */
+ brw_swap_page(rw, page, dev, zones, block_size);
+ return 1;
+}
+
+static struct swap_ops blkdevfile_swap_ops = {
+ blkdevfile_swap_open,
+ blkdevfile_swap_release,
+ blkdevfile_rw_page
+ };
+
+int __init blkdev_swap_init(void)
+{
+ (void)register_swap_method(BLKDEV_SWAP_ID, &blkdev_swap_ops);
+ (void)register_swap_method(BLKDEV_FILE_SWAP_ID, &blkdevfile_swap_ops);
+ return 0;
+}
+
+void __exit blkdev_swap_exit(void)
+{
+ unregister_swap_method(BLKDEV_SWAP_ID);
+ unregister_swap_method(BLKDEV_FILE_SWAP_ID);
+}
+
+module_init(blkdev_swap_init)
+module_exit(blkdev_swap_exit)
diff -uaNr linux-2.4.21/fs/buffer.c linux-2.4.21-1APTUS/fs/buffer.c
--- linux-2.4.21/fs/buffer.c 2003-06-22 17:35:00.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/buffer.c 2003-06-23 01:57:44.000000000 +0800
@@ -737,7 +737,7 @@
bh->b_private = private;
}
-static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
+void end_buffer_io_async(struct buffer_head * bh, int uptodate)
{
static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
diff -uaNr linux-2.4.21/fs/Config.in linux-2.4.21-1APTUS/fs/Config.in
--- linux-2.4.21/fs/Config.in 2002-11-29 07:53:15.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/Config.in 2003-06-23 11:08:34.000000000 +0800
@@ -4,6 +4,8 @@
mainmenu_option next_comment
comment 'File systems'
+tristate 'Swapping to block devices and local filesystems' CONFIG_BLOCKDEV_SWAP
+
bool 'Quota support' CONFIG_QUOTA
tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
diff -uaNr linux-2.4.21/fs/Makefile linux-2.4.21-1APTUS/fs/Makefile
--- linux-2.4.21/fs/Makefile 2002-11-29 07:53:15.000000000 +0800
+++ linux-2.4.21-1APTUS/fs/Makefile 2003-06-22 19:53:12.000000000 +0800
@@ -82,5 +82,6 @@
# persistent filesystems
obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
+obj-$(CONFIG_BLOCKDEV_SWAP) += blkdev_swap.o
include $(TOPDIR)/Rules.make
diff -uaNr linux-2.4.21/include/linux/fs.h linux-2.4.21-1APTUS/include/linux/fs.h
--- linux-2.4.21/include/linux/fs.h 2003-06-22 17:35:06.000000000 +0800
+++ linux-2.4.21-1APTUS/include/linux/fs.h 2003-06-23 01:15:04.000000000 +0800
@@ -1128,6 +1128,7 @@
extern void refile_buffer(struct buffer_head * buf);
extern void create_empty_buffers(struct page *, kdev_t, unsigned long);
extern void end_buffer_io_sync(struct buffer_head *bh, int uptodate);
+extern void end_buffer_io_async(struct buffer_head * bh, int uptodate);
/* reiserfs_writepage needs this */
extern void set_buffer_async_io(struct buffer_head *bh) ;
diff -uaNr linux-2.4.21/include/linux/swap.h linux-2.4.21-1APTUS/include/linux/swap.h
--- linux-2.4.21/include/linux/swap.h 2003-06-22 17:35:07.000000000 +0800
+++ linux-2.4.21-1APTUS/include/linux/swap.h 2003-06-23 01:38:41.000000000 +0800
@@ -58,15 +58,29 @@
#define SWAP_MAP_MAX 0x7fff
#define SWAP_MAP_BAD 0x8000
+struct swap_ops {
+ int (*open)(struct file *swapf, void **data);
+ int (*release)(struct file *swapf, void *data);
+ int (*rw_page)(int rw,
+ struct page *page, unsigned long offset, void *data);
+};
+
+struct swap_method {
+ struct swap_method *next;
+ char * name;
+ struct swap_ops *ops;
+ int use_count;
+};
+
/*
* The in-memory structure used to track swap areas.
*/
struct swap_info_struct {
unsigned int flags;
- kdev_t swap_device;
+ struct file *swap_file;
+ struct swap_method *method;
+ void *data;
spinlock_t sdev_lock;
- struct dentry * swap_file;
- struct vfsmount *swap_vfsmnt;
unsigned short * swap_map;
unsigned int lowest_bit;
unsigned int highest_bit;
@@ -142,10 +156,15 @@
extern unsigned int nr_swapfiles;
extern struct swap_info_struct swap_info[];
extern int is_swap_partition(kdev_t);
+extern int register_swap_method(char *name, struct swap_ops *ops);
+extern int unregister_swap_method(char *name);
+extern int swap_run_test(int (*test_fct)(unsigned int flags,
+ struct file *swap_file,
+ void *testdata), void *testdata);
extern void si_swapinfo(struct sysinfo *);
extern swp_entry_t get_swap_page(void);
-extern void get_swaphandle_info(swp_entry_t, unsigned long *, kdev_t *,
- struct inode **);
+struct swap_method *get_swaphandle_info(swp_entry_t entry,
+ unsigned long *offset, void **data);
extern int swap_duplicate(swp_entry_t);
extern int valid_swaphandles(swp_entry_t, unsigned long *);
extern void swap_free(swp_entry_t);
diff -uaNr linux-2.4.21/kernel/ksyms.c linux-2.4.21-1APTUS/kernel/ksyms.c
--- linux-2.4.21/kernel/ksyms.c 2003-06-22 18:34:45.000000000 +0800
+++ linux-2.4.21-1APTUS/kernel/ksyms.c 2003-06-23 01:02:29.000000000 +0800
@@ -41,6 +41,7 @@
#include <linux/mm.h>
#include <linux/capability.h>
#include <linux/highuid.h>
+#include <linux/swapctl.h>
#include <linux/brlock.h>
#include <linux/fs.h>
#include <linux/tty.h>
@@ -93,6 +94,10 @@
EXPORT_SYMBOL(kallsyms_symbol_to_address);
EXPORT_SYMBOL(kallsyms_address_to_symbol);
#endif
+EXPORT_SYMBOL(nr_free_pages);
+EXPORT_SYMBOL(register_swap_method);
+EXPORT_SYMBOL(unregister_swap_method);
+EXPORT_SYMBOL(swap_run_test);
/* process memory management */
EXPORT_SYMBOL(do_mmap_pgoff);
diff -uaNr linux-2.4.21/mm/page_io.c linux-2.4.21-1APTUS/mm/page_io.c
--- linux-2.4.21/mm/page_io.c 2002-11-29 07:53:15.000000000 +0800
+++ linux-2.4.21-1APTUS/mm/page_io.c 2003-06-23 00:32:31.000000000 +0800
@@ -32,15 +32,15 @@
* atomic, which is particularly important when we are trying to ensure
* that shared pages stay shared while being swapped.
*/
-
+/* David: Don't know is this is corrct or not, since 2.4.14, the rw never
+ * checked for WRITE. Not sure will we cause a problem here if we check for
+ * WRITE and start I/O and wait for completion.
+ */
static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
{
unsigned long offset;
- int zones[PAGE_SIZE/512];
- int zones_used;
- kdev_t dev = 0;
- int block_size;
- struct inode *swapf = 0;
+ struct swap_method *method;
+ void *data;
if (rw == READ) {
ClearPageUptodate(page);
@@ -48,31 +48,21 @@
} else
kstat.pswpout++;
- get_swaphandle_info(entry, &offset, &dev, &swapf);
- if (dev) {
- zones[0] = offset;
- zones_used = 1;
- block_size = PAGE_SIZE;
- } else if (swapf) {
- int i, j;
- unsigned int block = offset
- << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
-
- block_size = swapf->i_sb->s_blocksize;
- for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
- if (!(zones[i] = bmap(swapf,block++))) {
- printk("rw_swap_page: bad swap file\n");
- return 0;
- }
- zones_used = i;
- dev = swapf->i_dev;
- } else {
- return 0;
+ method = get_swaphandle_info(entry, &offset, &data);
+
+ if (method) {
+ if (!method->ops->rw_page(rw, page, offset, data)) {
+ return 0;
+ }
+ /* Note! For consistency we do all of the logic,
+ * decrementing the page count, and unlocking the page in the
+ * swap lock map - in the IO completion handler.
+ */
+ return 1;
+
}
- /* block_size == PAGE_SIZE/zones_used */
- brw_page(rw, page, dev, zones, block_size);
- return 1;
+ return 0;
}
/*
diff -uaNr linux-2.4.21/mm/swapfile.c linux-2.4.21-1APTUS/mm/swapfile.c
--- linux-2.4.21/mm/swapfile.c 2003-06-22 17:35:08.000000000 +0800
+++ linux-2.4.21-1APTUS/mm/swapfile.c 2003-06-23 11:09:17.000000000 +0800
@@ -14,9 +14,15 @@
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/shm.h>
-
+#include <linux/file.h>
+#include <linux/compiler.h>
+#include <linux/nfs_fs.h>
#include <asm/pgtable.h>
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
spinlock_t swaplock = SPIN_LOCK_UNLOCKED;
unsigned int nr_swapfiles;
int total_swap_pages;
@@ -31,8 +37,78 @@
struct swap_info_struct swap_info[MAX_SWAPFILES];
+static struct swap_method *swap_methods = NULL;
+
#define SWAPFILE_CLUSTER 256
+int register_swap_method(char *name, struct swap_ops *ops)
+{
+ struct swap_method *pos;
+ struct swap_method *new;
+ int result = 0;
+
+ lock_kernel();
+
+ for (pos = swap_methods; pos; pos = pos->next) {
+ if (strcmp(pos->name, name) == 0) {
+ printk(KERN_ERR "register_swap_method: "
+ "method %s already registered\n", name);
+ result = -EBUSY;
+ goto out;
+ }
+ }
+
+ if (!(new = kmalloc(sizeof(*new), GFP_KERNEL))) {
+ printk(KERN_ERR "register_swap_method: "
+ "no memory for new method \"%s\"\n", name);
+ result = -ENOMEM;
+ goto out;
+ }
+
+ new->name = name;
+ new->ops = ops;
+ new->use_count = 0;
+
+ /* ok, insert at top of list */
+ printk("register_swap_method: method %s\n", name);
+ new->next = swap_methods;
+ swap_methods = new;
+ out:
+ unlock_kernel();
+ return result;
+}
+
+int unregister_swap_method(char *name)
+{
+ struct swap_method **method, *next;
+ int result = 0;
+
+ lock_kernel();
+
+ for (method = &swap_methods; *method; method = &(*method)->next) {
+ if (strcmp((*method)->name, name) == 0) {
+ if ((*method)->use_count > 0) {
+ printk(KERN_ERR "unregister_swap_method: "
+ "method \"%s\" is in use\n", name);
+ result = -EBUSY;
+ goto out;
+ }
+
+ next = (*method)->next;
+ kfree(*method);
+ *method = next;
+ printk("unregister_swap_method: method %s\n", name);
+ goto out;
+ }
+ }
+ /* not found */
+ printk("unregister_swap_method: no such method %s\n", name);
+ result = -ENOENT;
+ out:
+ unlock_kernel();
+ return result;
+}
+
static inline int scan_swap_map(struct swap_info_struct *si)
{
unsigned long offset;
@@ -717,7 +793,7 @@
err = user_path_walk(specialfile, &nd);
if (err)
- goto out;
+ return err;
lock_kernel();
prev = -1;
@@ -725,15 +801,20 @@
for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
p = swap_info + type;
if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
- if (p->swap_file == nd.dentry)
- break;
+ if (p->swap_file &&
+ p->swap_file->f_dentry == nd.dentry)
+ break;
}
prev = type;
}
err = -EINVAL;
+ /* p->swap_file contains all needed info, no need to keep nd, so
+ * release it now.
+ */
+ path_release(&nd);
if (type < 0) {
swap_list_unlock();
- goto out_dput;
+ goto out;
}
if (prev < 0) {
@@ -767,19 +848,18 @@
total_swap_pages += p->pages;
p->flags = SWP_WRITEOK;
swap_list_unlock();
- goto out_dput;
+ goto out;
}
- if (p->swap_device)
- blkdev_put(p->swap_file->d_inode->i_bdev, BDEV_SWAP);
- path_release(&nd);
+ if (p->method->ops->release)
+ p->method->ops->release(p->swap_file, p->data);
swap_list_lock();
swap_device_lock(p);
- nd.mnt = p->swap_vfsmnt;
- nd.dentry = p->swap_file;
- p->swap_vfsmnt = NULL;
+ p->method->use_count --;
+ p->method = NULL;
+ p->data = NULL;
+ filp_close(p->swap_file, NULL);
p->swap_file = NULL;
- p->swap_device = 0;
p->max = 0;
swap_map = p->swap_map;
p->swap_map = NULL;
@@ -789,10 +869,8 @@
vfree(swap_map);
err = 0;
-out_dput:
- unlock_kernel();
- path_release(&nd);
out:
+ unlock_kernel();
return err;
}
@@ -805,18 +883,17 @@
if (!page)
return -ENOMEM;
- len += sprintf(buf, "Filename\t\t\tType\t\tSize\tUsed\tPriority\n");
+ len += sprintf(buf, "%-32s%-16s%-8s%-8sPriority\n",
+ "Filename", "Type", "Size", "Used");
for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
if ((ptr->flags & SWP_USED) && ptr->swap_map) {
- char * path = d_path(ptr->swap_file, ptr->swap_vfsmnt,
- page, PAGE_SIZE);
+ char * path = d_path(ptr->swap_file->f_dentry,
+ ptr->swap_file->f_vfsmnt,
+ page, PAGE_SIZE);
len += sprintf(buf + len, "%-31s ", path);
- if (!ptr->swap_device)
- len += sprintf(buf + len, "file\t\t");
- else
- len += sprintf(buf + len, "partition\t");
+ len += sprintf(buf + len, "%-15s ", ptr->method->name);
usedswap = 0;
for (j = 0; j < ptr->max; ++j)
@@ -827,7 +904,7 @@
default:
usedswap++;
}
- len += sprintf(buf + len, "%d\t%d\t%d\n", ptr->pages << (PAGE_SHIFT - 10),
+ len += sprintf(buf + len, "%-8d%-8d%d\n", ptr->pages << (PAGE_SHIFT - 10),
usedswap << (PAGE_SHIFT - 10), ptr->prio);
}
}
@@ -835,28 +912,89 @@
return len;
}
-int is_swap_partition(kdev_t dev) {
+/* apply a test function to all active swap objects. E.g. for checking
+ * whether a partition is used for swapping
+ */
+int swap_run_test(int (*test_fct)(unsigned int flags,
+ struct file * swap_file,
+ void *testdata), void *testdata)
+{
struct swap_info_struct *ptr = swap_info;
int i;
for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
- if (ptr->flags & SWP_USED)
- if (ptr->swap_device == dev)
- return 1;
+ if (ptr->swap_file &&
+ test_fct(ptr->flags, ptr->swap_file, testdata))
+ return 1;
}
return 0;
}
+/* Walk through the list of known swap method until somebody wants to
+ * handle this file. Pick the first one which claims to be able to
+ * swap to this kind of file.
+ *
+ * return value: < 0: error, 0: not found, > 0: swapfilesize
+ */
+int find_swap_method(struct file *swap_file,
+ struct swap_info_struct *p)
+{
+ int swapfilesize = 0;
+ struct swap_method *method;
+
+ p->method = NULL;
+ for (method = swap_methods; method; method = method->next) {
+ swapfilesize = method->ops->open(swap_file, &p->data);
+ if (swapfilesize == 0) {
+ continue;
+ }
+ if (swapfilesize > 0) {
+ p->method = method;
+ p->method->use_count ++;
+ p->swap_file = swap_file;
+ break;
+ }
+ if (swapfilesize < 0) {
+ break;
+ }
+ }
+ return swapfilesize;
+}
+
+/* swap_run_test() applies this hook to all swapfiles until it returns
+ * "1". If it never return "1", the result of swap_run_test() is "0",
+ * otherwise "1".
+ */
+static int is_swap_partition_hook(unsigned int flags, struct file *swap_file,
+ void *testdata)
+{
+ kdev_t swap_dev = S_ISBLK(swap_file->f_dentry->d_inode->i_mode)
+ ? swap_file->f_dentry->d_inode->i_rdev : 0;
+ kdev_t dev = *((kdev_t *)testdata);
+
+ if (flags & SWP_USED && dev == swap_dev) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/* A wrapper to the swap_run_test() which test for swap methods
+ */
+int is_swap_partition(kdev_t dev) {
+ return swap_run_test(is_swap_partition_hook, &dev);
+}
+
/*
* Written 01/25/92 by Simmule Turner, heavily changed by Linus.
+ * 22nd June 2003 David Chow <davidchow@shaolinmicro.com>
+ * Modified to enable the swap method hooks
*
* The swapon system call
*/
asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
{
struct swap_info_struct * p;
- struct nameidata nd;
- struct inode * swap_inode;
unsigned int type;
int i, j, prev;
int error;
@@ -866,9 +1004,9 @@
int nr_good_pages = 0;
unsigned long maxpages = 1;
int swapfilesize;
- struct block_device *bdev = NULL;
unsigned short *swap_map;
-
+ char * tmp_specialfile;
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
lock_kernel();
@@ -886,8 +1024,7 @@
nr_swapfiles = type+1;
p->flags = SWP_USED;
p->swap_file = NULL;
- p->swap_vfsmnt = NULL;
- p->swap_device = 0;
+ p->method = NULL;
p->swap_map = NULL;
p->lowest_bit = 0;
p->highest_bit = 0;
@@ -901,58 +1038,69 @@
p->prio = --least_priority;
}
swap_list_unlock();
- error = user_path_walk(specialfile, &nd);
- if (error)
- goto bad_swap_2;
-
- p->swap_file = nd.dentry;
- p->swap_vfsmnt = nd.mnt;
- swap_inode = nd.dentry->d_inode;
- error = -EINVAL;
+ /* Open the swap using filp_open. Bail out on any errors. */
+ tmp_specialfile = getname(specialfile);
+ if (IS_ERR(tmp_specialfile)) {
+ error = PTR_ERR(tmp_specialfile);
+ goto bad_swap_2;
+ }
+ p->swap_file = filp_open(tmp_specialfile, O_RDWR, 0600);
+ putname(tmp_specialfile);
+ if (IS_ERR(p->swap_file)) {
+ error = PTR_ERR(p->swap_file);
+ goto bad_swap_1;
+ }
- if (S_ISBLK(swap_inode->i_mode)) {
- kdev_t dev = swap_inode->i_rdev;
- struct block_device_operations *bdops;
- devfs_handle_t de;
-
- if (is_mounted(dev)) {
- error = -EBUSY;
- goto bad_swap_2;
- }
+ error = -EINVAL;
- p->swap_device = dev;
- set_blocksize(dev, PAGE_SIZE);
-
- bd_acquire(swap_inode);
- bdev = swap_inode->i_bdev;
- de = devfs_get_handle_from_inode(swap_inode);
- bdops = devfs_get_ops(de); /* Increments module use count */
- if (bdops) bdev->bd_op = bdops;
-
- error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_SWAP);
- devfs_put_ops(de);/*Decrement module use count now we're safe*/
- if (error)
- goto bad_swap_2;
- set_blocksize(dev, PAGE_SIZE);
- error = -ENODEV;
- if (!dev || (blk_size[MAJOR(dev)] &&
- !blk_size[MAJOR(dev)][MINOR(dev)]))
- goto bad_swap;
- swapfilesize = 0;
- if (blk_size[MAJOR(dev)])
- swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
- >> (PAGE_SHIFT - 10);
- } else if (S_ISREG(swap_inode->i_mode))
- swapfilesize = swap_inode->i_size >> PAGE_SHIFT;
- else
- goto bad_swap;
+ swapfilesize = find_swap_method(p->swap_file, p);
+ if (swapfilesize < 0) {
+ error = swapfilesize;
+ filp_close(p->swap_file, NULL);
+ goto bad_swap_1;
+ }
+
+#ifdef CONFIG_KMOD
+ if (swapfilesize == 0) {
+ if ((p->swap_file->f_dentry->d_sb
+ && (p->swap_file->f_dentry->d_sb->s_type->fs_flags & FS_REQUIRES_DEV))
+ || (p->swap_file->f_dentry->d_inode
+ && S_ISBLK(p->swap_file->f_dentry->d_inode->i_mode))) {
+ /* It looks like a block device filesystem */
+ (void)request_module("blkdev_swap");
+ } else {
+ /* User may specify which swap module it use */
+ (void)request_module("swapfile-mod");
+ }
+
+ swapfilesize = find_swap_method(p->swap_file, p);
+ if (swapfilesize < 0) {
+ error = swapfilesize;
+ filp_close(p->swap_file, NULL);
+ goto bad_swap_1;
+ }
+ }
+#endif
+ if (swapfilesize == 0) {
+ printk("Invalid swap file\n");
+ filp_close(p->swap_file, NULL);
+ goto bad_swap_1; /* free swap map */
+ }
+
+ /* After this point, the swap-file has been opened by the swap
+ * method. We must make sure to use the bad_swap label for any
+ * errors.
+ */
error = -EBUSY;
+
for (i = 0 ; i < nr_swapfiles ; i++) {
struct swap_info_struct *q = &swap_info[i];
if (i == type || !q->swap_file)
continue;
- if (swap_inode->i_mapping == q->swap_file->d_inode->i_mapping)
+ if (p->swap_file->f_dentry->d_inode->i_mapping
+ ==
+ q->swap_file->f_dentry->d_inode->i_mapping)
goto bad_swap;
}
@@ -1088,17 +1236,25 @@
swap_list_unlock();
error = 0;
goto out;
+
bad_swap:
- if (bdev)
- blkdev_put(bdev, BDEV_SWAP);
+ if (p->method->ops->release)
+ p->method->ops->release(p->swap_file, p->data);
+ swap_list_lock();
+ p->method->use_count --;
+ p->method = NULL;
+ p->data = NULL;
+ swap_list_unlock();
+
+bad_swap_1:
+ swap_list_lock();
+ p->swap_file = NULL;
+ swap_list_unlock();
+
bad_swap_2:
+
swap_list_lock();
swap_map = p->swap_map;
- nd.mnt = p->swap_vfsmnt;
- nd.dentry = p->swap_file;
- p->swap_device = 0;
- p->swap_file = NULL;
- p->swap_vfsmnt = NULL;
p->swap_map = NULL;
p->flags = 0;
if (!(swap_flags & SWAP_FLAG_PREFER))
@@ -1106,7 +1262,7 @@
swap_list_unlock();
if (swap_map)
vfree(swap_map);
- path_release(&nd);
+
out:
if (swap_header)
free_page((long) swap_header);
@@ -1181,8 +1337,8 @@
/*
* Prior swap_duplicate protects against swap device deletion.
*/
-void get_swaphandle_info(swp_entry_t entry, unsigned long *offset,
- kdev_t *dev, struct inode **swapf)
+struct swap_method *get_swaphandle_info(swp_entry_t entry,
+ unsigned long *offset, void **data)
{
unsigned long type;
struct swap_info_struct *p;
@@ -1190,32 +1346,26 @@
type = SWP_TYPE(entry);
if (type >= nr_swapfiles) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_file, entry.val);
- return;
+ return NULL;
}
p = &swap_info[type];
*offset = SWP_OFFSET(entry);
if (*offset >= p->max && *offset != 0) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_offset, entry.val);
- return;
+ return NULL;
}
if (p->swap_map && !p->swap_map[*offset]) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_offset, entry.val);
- return;
+ return NULL;
}
if (!(p->flags & SWP_USED)) {
printk(KERN_ERR "rw_swap_page: %s%08lx\n", Unused_file, entry.val);
- return;
+ return NULL;
}
- if (p->swap_device) {
- *dev = p->swap_device;
- } else if (p->swap_file) {
- *swapf = p->swap_file->d_inode;
- } else {
- printk(KERN_ERR "rw_swap_page: no swap file or device\n");
- }
- return;
+ *data = p->data;
+ return p->method;
}
/*
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2003-06-23 15:51 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-23 15:04 swap modules David Chow
2003-06-23 15:51 ` (corrected) " David Chow
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox