This is barry-scott's patch:

[ 1231069 ] ioctl has problem with -ive request codes

by using the 'I' not the 'i' format code to PyArg_ParseTuple().

Backport candidate?  Maybe...
diff --git a/Misc/NEWS b/Misc/NEWS
index f168fa1..1bbec39 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -117,6 +117,10 @@
 Extension Modules
 -----------------
 
+- Patch #1231069: The fcntl.ioctl function now uses the 'I' code for
+  the request code argument, which results in more C-like behaviour
+  for large or negative values.
+
 - Bug #1234979: For the argument of thread.Lock.acquire, the Windows
   implemented treated all integer values except 1 as false.
 
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index 54f3a2e..eb5189e 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -102,7 +102,7 @@
 	int mutate_arg = 1;
 	char buf[1024];
 
-	if (PyArg_ParseTuple(args, "O&iw#|i:ioctl",
+	if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",
                              conv_descriptor, &fd, &code, 
 			     &str, &len, &mutate_arg)) {
 		char *arg;
@@ -151,7 +151,7 @@
 	}
 
 	PyErr_Clear();
-	if (PyArg_ParseTuple(args, "O&is#:ioctl",
+	if (PyArg_ParseTuple(args, "O&Is#:ioctl",
                              conv_descriptor, &fd, &code, &str, &len)) {
 		if (len > sizeof buf) {
 			PyErr_SetString(PyExc_ValueError,
@@ -172,7 +172,7 @@
 	PyErr_Clear();
 	arg = 0;
 	if (!PyArg_ParseTuple(args,
-	     "O&i|i;ioctl requires a file or file descriptor,"
+	     "O&I|i;ioctl requires a file or file descriptor,"
 	     " an integer and optionally a integer or buffer argument",
 			      conv_descriptor, &fd, &code, &arg)) {
 	  return NULL;