/* .+

.identifier : $Id$
.context    : portio python extension
.title      : distutils setup
.kind	    : python source
.author     : Fabrizio Pollastri <mxgbot@gmail.com>
.site	    : Torino - Italy
.creation   : 16-Feb-2006
.copyright  : (c) 2006-2012 Fabrizio Pollastri
              (c) 2012 Stjepan Henc <sthenc@gmail.com> python 3 porting.
.license    : GNU General Public License (see .copying below)

.copying

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

.- */

#include "Python.h"
#include <sys/io.h>

static PyObject *pio_outb(PyObject *self,PyObject *args)
{
  unsigned char data;
  unsigned short int port;
  if (!PyArg_ParseTuple(args,"BH",&data,&port)) return NULL;
  outb(data,port);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outw(PyObject *self,PyObject *args)
{
  unsigned short int data;
  unsigned short int port;
  if (!PyArg_ParseTuple(args,"HH",&data,&port)) return NULL;
  outw(data,port);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outl(PyObject *self,PyObject *args)
{
  unsigned int data;
  unsigned short int port;
  if (!PyArg_ParseTuple(args,"IH",&data,&port)) return NULL;
  outl(data,port);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outb_p(PyObject *self,PyObject *args)
{
  unsigned char data;
  unsigned short int port;
  if (!PyArg_ParseTuple(args,"BH",&data,&port)) return NULL;
  outb_p(data,port);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outw_p(PyObject *self,PyObject *args)
{
  unsigned short int data;
  unsigned short int port;
  if (!PyArg_ParseTuple(args,"HH",&data,&port)) return NULL;
  outw_p(data,port);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outl_p(PyObject *self,PyObject *args)
{
  unsigned int data;
  unsigned short int port;
  if (!PyArg_ParseTuple(args,"IH",&data,&port)) return NULL;
  outl_p(data,port);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outsb(PyObject *self,PyObject *args)
{
  unsigned short int port;
  Py_buffer string;
  unsigned long int count;
  if (!PyArg_ParseTuple(args,"Hs*k",&port,&string,&count)) return NULL;
  outsb(port,string.buf,count);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outsw(PyObject *self,PyObject *args)
{
  unsigned short int port;
  Py_buffer string;
  unsigned long int count;
  if (!PyArg_ParseTuple(args,"Hs*k",&port,&string,&count)) return NULL;
  outsw(port,string.buf,count);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_outsl(PyObject *self,PyObject *args)
{
  unsigned short int port;
  Py_buffer string;
  unsigned long int count;
  if (!PyArg_ParseTuple(args,"Hs*k",&port,&string,&count)) return NULL;
  outsl(port,string.buf,count);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_inb(PyObject *self,PyObject *args)
{
  unsigned short int port;
  unsigned char data;
  if (!PyArg_ParseTuple(args,"H",&port)) return NULL;
  data = inb(port);
  return Py_BuildValue("B",data);
}

static PyObject *pio_inw(PyObject *self,PyObject *args)
{
  unsigned short int port;
  unsigned short int data;
  if (!PyArg_ParseTuple(args,"H",&port)) return NULL;
  data = inw(port);
  return Py_BuildValue("H",data);
}

static PyObject *pio_inl(PyObject *self,PyObject *args)
{
  unsigned short int port;
  unsigned int data;
  if (!PyArg_ParseTuple(args,"H",&port)) return NULL;
  data = inl(port);
  return Py_BuildValue("I",data);
}

static PyObject *pio_inb_p(PyObject *self,PyObject *args)
{
  unsigned short int port;
  unsigned char data;
  if (!PyArg_ParseTuple(args,"H",&port)) return NULL;
  data = inb_p(port);
  return Py_BuildValue("B",data);
}

static PyObject *pio_inw_p(PyObject *self,PyObject *args)
{
  unsigned short int port;
  unsigned short int data;
  if (!PyArg_ParseTuple(args,"H",&port)) return NULL;
  data = inw_p(port);
  return Py_BuildValue("H",data);
}

static PyObject *pio_inl_p(PyObject *self,PyObject *args)
{
  unsigned short int port;
  unsigned int data;
  if (!PyArg_ParseTuple(args,"H",&port)) return NULL;
  data = inl_p(port);
  return Py_BuildValue("I",data);
}

static PyObject *pio_insb(PyObject *self,PyObject *args)
{
  unsigned short int port;
  Py_buffer string;
  unsigned long int count;
  if (!PyArg_ParseTuple(args,"Hs*k",&port,&string,&count)) return NULL;
  insb(port,string.buf,count);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_insw(PyObject *self,PyObject *args)
{
  unsigned short int port;
  Py_buffer string;
  unsigned long int count;
  if (!PyArg_ParseTuple(args,"Hs*k",&port,&string,&count)) return NULL;
  insw(port,string.buf,count);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_insl(PyObject *self,PyObject *args)
{
  unsigned short int port;
  Py_buffer string;
  unsigned long int count;
  if (!PyArg_ParseTuple(args,"Hs*k",&port,&string,&count)) return NULL;
  insl(port,string.buf,count);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyObject *pio_ioperm(PyObject *self,PyObject *args)
{
  unsigned long int from;
  unsigned long int extent;
  int enable;
  int status;
  if (!PyArg_ParseTuple(args,"kki",&from,&extent,&enable)) return NULL;
  status = ioperm(from,extent,enable);
  if (status) status = errno;
  return Py_BuildValue("i",status);
}

static PyObject *pio_iopl(PyObject *self,PyObject *args)
{
  int level;
  int status;
  if (!PyArg_ParseTuple(args,"i",&level)) return NULL;
  status = iopl(level);
  if (status) status = errno;
  return Py_BuildValue("i",status);
}

/* List of methods defined in the module */

static struct PyMethodDef methods[] = {
  {"outb",(PyCFunction)pio_outb,METH_VARARGS,NULL},
  {"outw",(PyCFunction)pio_outw,METH_VARARGS,NULL},
  {"outl",(PyCFunction)pio_outl,METH_VARARGS,NULL},
  {"outb_p",(PyCFunction)pio_outb_p,METH_VARARGS,NULL},
  {"outw_p",(PyCFunction)pio_outw_p,METH_VARARGS,NULL},
  {"outl_p",(PyCFunction)pio_outl_p,METH_VARARGS,NULL},
  {"outsb",(PyCFunction)pio_outsb,METH_VARARGS,NULL},
  {"outsw",(PyCFunction)pio_outsw,METH_VARARGS,NULL},
  {"outsl",(PyCFunction)pio_outsl,METH_VARARGS,NULL},
  {"inb",(PyCFunction)pio_inb,METH_VARARGS,NULL},
  {"inw",(PyCFunction)pio_inw,METH_VARARGS,NULL},
  {"inl",(PyCFunction)pio_inl,METH_VARARGS,NULL},
  {"inb_p",(PyCFunction)pio_inb_p,METH_VARARGS,NULL},
  {"inw_p",(PyCFunction)pio_inw_p,METH_VARARGS,NULL},
  {"inl_p",(PyCFunction)pio_inl_p,METH_VARARGS,NULL},
  {"insb",(PyCFunction)pio_insb,METH_VARARGS,NULL},
  {"insw",(PyCFunction)pio_insw,METH_VARARGS,NULL},
  {"insl",(PyCFunction)pio_insl,METH_VARARGS,NULL},
  {"ioperm",(PyCFunction)pio_ioperm,METH_VARARGS,NULL},
  {"iopl",(PyCFunction)pio_iopl,METH_VARARGS,NULL},
  {NULL, (PyCFunction)NULL, 0, NULL}
};

/* module init function */

static char documentation[] ="%(DOCUMENTATION)s";

/* module init for both python < 3.0 and >= 3.0 */

static PyObject *Error;

#if PY_MAJOR_VERSION < 3	/* is python < 3.0 */

PyMODINIT_FUNC
initportio(void)
{
  PyObject *m;
  m = Py_InitModule3("portio", methods, documentation);
  if(m == NULL)
    return;

  /* add module specific exception */
  Error = PyErr_NewException("portio.error", NULL, NULL);
  Py_INCREF(Error);
  PyModule_AddObject(m, "error", Error);
}

#else				/* is python >= 3.0 */

static struct PyModuleDef portiomodule = {
   PyModuleDef_HEAD_INIT, "portio", documentation, -1, methods
};

PyMODINIT_FUNC
PyInit_portio(void)
{
  PyObject *m;
  m = PyModule_Create(&portiomodule);
  if(m == NULL)
    return NULL;

  /* add module specific exception */
  Error = PyErr_NewException("portio.error", NULL, NULL);
  Py_INCREF(Error);
  PyModule_AddObject(m, "error", Error);
	
  return m;
}

#endif

/* end */
