logo       


[6/14] Orinoco driver updates - cleanup PCI initialization: msg#00024

Subject: [6/14] Orinoco driver updates - cleanup PCI initialization
Update the initialization code in the various PCI incarnations of the
orinoco driver.  This applies similar initialization and shutdown
cleanups to the orinoco_pci, orinoco_plx and orinoco_tmd drivers.  It
also adds COR reset support to the orinoco_plx and orinoco_tmd
drivers, improves PCI power management support in the orinoco_pci
driver and adds a couple of extra supported cards to the ID tables.

Signed-off-by: David Gibson 
<hermes-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@xxxxxxxxxxxxxxxx>

Index: working-2.6/drivers/net/wireless/orinoco_pci.c
===================================================================
--- working-2.6.orig/drivers/net/wireless/orinoco_pci.c 2005-01-12 
15:47:48.215477920 +1100
+++ working-2.6/drivers/net/wireless/orinoco_pci.c      2005-01-12 
16:10:57.324301280 +1100
@@ -129,6 +129,11 @@
 #define HERMES_PCI_COR_OFFT    (500)           /* ms */
 #define HERMES_PCI_COR_BUSYT   (500)           /* ms */
 
+/* Orinoco PCI specific data */
+struct orinoco_pci_card {
+       void __iomem *pci_ioaddr;
+};
+
 /*
  * Do a soft reset of the PCI card using the Configuration Option Register
  * We need this to get going...
@@ -164,8 +169,9 @@
                mdelay(1);
                reg = hermes_read_regn(hw, CMD);
        }
-       /* Did we timeout ? */
-       if(time_after_eq(jiffies, timeout)) {
+
+       /* Still busy? */
+       if (reg & HERMES_CMD_BUSY) {
                printk(KERN_ERR PFX "Busy timeout\n");
                return -ETIMEDOUT;
        }
@@ -184,6 +190,7 @@
        u16 __iomem *pci_ioaddr = NULL;
        unsigned long pci_iolen;
        struct orinoco_private *priv = NULL;
+       struct orinoco_pci_card *card;
        struct net_device *dev = NULL;
 
        err = pci_enable_device(pdev);
@@ -192,24 +199,31 @@
                return err;
        }
 
+       err = pci_request_regions(pdev, DRIVER_NAME);
+       if (err != 0) {
+               printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+               goto fail_resources;
+       }
+
        /* Resource 0 is mapped to the hermes registers */
        pci_iorange = pci_resource_start(pdev, 0);
        pci_iolen = pci_resource_len(pdev, 0);
        pci_ioaddr = ioremap(pci_iorange, pci_iolen);
-       if (! pci_iorange) {
+       if (!pci_iorange) {
                printk(KERN_ERR PFX "Cannot remap hardware registers\n");
-               goto fail;
+               goto fail_map;
        }
 
        /* Allocate network device */
-       dev = alloc_orinocodev(0, NULL);
+       dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
        if (! dev) {
                err = -ENOMEM;
-               goto fail;
+               goto fail_alloc;
        }
 
        priv = netdev_priv(dev);
-       dev->base_addr = (unsigned long) pci_ioaddr;
+       card = priv->card;
+       card->pci_ioaddr = pci_ioaddr;
        dev->mem_start = pci_iorange;
        dev->mem_end = pci_iorange + pci_iolen - 1;
        SET_MODULE_OWNER(dev);
@@ -226,14 +240,14 @@
        if (err) {
                printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
                err = -EBUSY;
-               goto fail;
+               goto fail_irq;
        }
        dev->irq = pdev->irq;
 
        /* Perform a COR reset to start the card */
-       if(orinoco_pci_cor_reset(priv) != 0) {
+       err = orinoco_pci_cor_reset(priv);
+       if (err) {
                printk(KERN_ERR PFX "Initial reset failed\n");
-               err = -ETIMEDOUT;
                goto fail;
        }
 
@@ -250,16 +264,19 @@
        return 0;
 
  fail:
-       if (dev) {
-               if (dev->irq)
-                       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
 
-               free_orinocodev(dev);
-       }
+ fail_irq:
+       pci_set_drvdata(pdev, NULL);
+       free_orinocodev(dev);
+
+ fail_alloc:
+       iounmap(pci_ioaddr);
 
-       if (pci_ioaddr)
-               iounmap(pci_ioaddr);
+ fail_map:
+       pci_release_regions(pdev);
 
+ fail_resources:
        pci_disable_device(pdev);
 
        return err;
@@ -269,18 +286,14 @@
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_pci_card *card = priv->card;
 
        unregister_netdev(dev);
-
-       if (dev->irq)
-               free_irq(dev->irq, dev);
-
-       if (priv->hw.iobase)
-               iounmap(priv->hw.iobase);
-
+       free_irq(dev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
-
+       iounmap(card->pci_ioaddr);
+       pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 
@@ -312,6 +325,9 @@
        
        orinoco_unlock(priv, &flags);
 
+       pci_save_state(pdev);
+       pci_set_power_state(pdev, 3);
+
        return 0;
 }
 
@@ -324,6 +340,9 @@
 
        printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);
 
+       pci_set_power_state(pdev, 0);
+       pci_restore_state(pdev);
+
        err = orinoco_reinit_firmware(dev);
        if (err) {
                printk(KERN_ERR "%s: Error %d re-initializing firmware on 
orinoco_pci_resume()\n",
@@ -354,6 +373,8 @@
        {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
        /* Intersil Prism 2.5 */
        {0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
+       /* Samsung MagicLAN SWL-2210P */
+       {0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,},
        {0,},
 };
 
Index: working-2.6/drivers/net/wireless/orinoco_plx.c
===================================================================
--- working-2.6.orig/drivers/net/wireless/orinoco_plx.c 2005-01-12 
15:47:48.216477768 +1100
+++ working-2.6/drivers/net/wireless/orinoco_plx.c      2004-11-05 
14:20:30.000000000 +1100
@@ -142,26 +142,68 @@
 #include "hermes.h"
 #include "orinoco.h"
 
-#define COR_OFFSET     (0x3e0/2) /* COR attribute offset of Prism2 PC card */
+#define COR_OFFSET     (0x3e0) /* COR attribute offset of Prism2 PC card */
 #define COR_VALUE      (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with 
interrupt in level trigger */
+#define COR_RESET     (0x80)   /* reset bit in the COR register */
+#define PLX_RESET_TIME (500)   /* milliseconds */
 
 #define PLX_INTCSR             0x4c /* Interrupt Control & Status Register */
 #define PLX_INTCSR_INTEN       (1<<6) /* Interrupt Enable bit */
 
-static const u16 cis_magic[] = {
-       0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067
+static const u8 cis_magic[] = {
+       0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
 };
 
+/* Orinoco PLX specific data */
+struct orinoco_plx_card {
+       void __iomem *attr_mem;
+};
+
+/*
+ * Do a soft reset of the card using the Configuration Option Register
+ */
+static int orinoco_plx_cor_reset(struct orinoco_private *priv)
+{
+       hermes_t *hw = &priv->hw;
+       struct orinoco_plx_card *card = priv->card;
+       u8 __iomem *attr_mem = card->attr_mem;
+       unsigned long timeout;
+       u16 reg;
+
+       writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET);
+       mdelay(1);
+
+       writeb(COR_VALUE, attr_mem + COR_OFFSET);
+       mdelay(1);
+
+       /* Just in case, wait more until the card is no longer busy */
+       timeout = jiffies + (PLX_RESET_TIME * HZ / 1000);
+       reg = hermes_read_regn(hw, CMD);
+       while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
+               mdelay(1);
+               reg = hermes_read_regn(hw, CMD);
+       }
+
+       /* Did we timeout ? */
+       if (reg & HERMES_CMD_BUSY) {
+               printk(KERN_ERR PFX "Busy timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+
 static int orinoco_plx_init_one(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
        int err = 0;
-       u16 __iomem *attr_mem = NULL;
-       u32 reg, addr;
+       u8 __iomem *attr_mem = NULL;
+       u32 csr_reg, plx_addr;
        struct orinoco_private *priv = NULL;
+       struct orinoco_plx_card *card;
        unsigned long pccard_ioaddr = 0;
        unsigned long pccard_iolen = 0;
-       u16 magic[8];
        struct net_device *dev = NULL;
        void __iomem *mem;
        int i;
@@ -169,78 +211,38 @@
        err = pci_enable_device(pdev);
        if (err) {
                printk(KERN_ERR PFX "Cannot enable PCI device\n");
-               return -EIO;
+               return err;
        }
 
-       /* Resource 2 is mapped to the PCMCIA space */
-       attr_mem = ioremap(pci_resource_start(pdev, 2), PAGE_SIZE);
-       if (!attr_mem)
+       err = pci_request_regions(pdev, DRIVER_NAME);
+       if (err != 0) {
+               printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
                goto fail_resources;
-
-       printk(KERN_DEBUG PFX "CIS: ");
-       for (i = 0; i < 16; i++) {
-               printk("%02X:", readw(attr_mem+i));
        }
-       printk("\n");
-
-       /* Verify whether PC card is present */
-       /* FIXME: we probably need to be smarted about this */
-       memcpy_fromio(magic, attr_mem, 16);
-       if (memcmp(magic, cis_magic, 16) != 0) {
-               printk(KERN_ERR PFX "The CIS value of Prism2 PC "
-                      "card is unexpected\n");
-               err = -EIO;
-               iounmap(attr_mem);
-               goto fail_resources;
-       }
-
-       /* PCMCIA COR is the first byte following CIS: this write should
-        * enable I/O mode and select level-triggered interrupts */
-       writew(COR_VALUE, attr_mem + COR_OFFSET);
-       mdelay(1);
-       reg = readw(attr_mem + COR_OFFSET);
-       iounmap(attr_mem);
 
-       if (reg != COR_VALUE) {
-               printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", reg);
-               goto fail_resources;
-       }                       
+       /* Resource 1 is mapped to PLX-specific registers */
+       plx_addr = pci_resource_start(pdev, 1);
 
-       /* bjoern: We need to tell the card to enable interrupts, in
-          case the serial eprom didn't do this already. See the
-          PLX9052 data book, p8-1 and 8-24 for reference. */
-       addr = pci_resource_start(pdev, 1);
-       reg = inl(addr+PLX_INTCSR);
-       if (reg & PLX_INTCSR_INTEN)
-               printk(KERN_DEBUG PFX "Local Interrupt already enabled\n");
-       else {
-               reg |= PLX_INTCSR_INTEN;
-               outl(reg, addr+PLX_INTCSR);
-               reg = inl(addr+PLX_INTCSR);
-               if(!(reg & PLX_INTCSR_INTEN)) {
-                       printk(KERN_ERR PFX "Couldn't enable Local 
Interrupts\n");
-                       goto fail_resources;
-               }
+       /* Resource 2 is mapped to the PCMCIA attribute memory */
+       attr_mem = ioremap(pci_resource_start(pdev, 2),
+                          pci_resource_len(pdev, 2));
+       if (!attr_mem) {
+               printk(KERN_ERR PFX "Cannot remap PCMCIA space\n");
+               goto fail_map_attr;
        }
 
        /* Resource 3 is mapped to the PCMCIA I/O address space */
        pccard_ioaddr = pci_resource_start(pdev, 3);
        pccard_iolen = pci_resource_len(pdev, 3);
-       if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
-               printk(KERN_ERR PFX "I/O resource 0x%lx @ 0x%lx busy\n",
-                      pccard_iolen, pccard_ioaddr);
-               err = -EBUSY;
-               goto fail_resources;
-       }
 
        mem = pci_iomap(pdev, 3, 0);
        if (!mem) {
                err = -ENOMEM;
-               goto fail_map;
+               goto fail_map_io;
        }
 
        /* Allocate network device */
-       dev = alloc_orinocodev(0, NULL);
+       dev = alloc_orinocodev(sizeof(*card), orinoco_plx_cor_reset);
        if (!dev) {
                printk(KERN_ERR PFX "Cannot allocate network device\n");
                err = -ENOMEM;
@@ -248,6 +250,8 @@
        }
 
        priv = netdev_priv(dev);
+       card = priv->card;
+       card->attr_mem = attr_mem;
        dev->base_addr = pccard_ioaddr;
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
@@ -268,6 +272,43 @@
        }
        dev->irq = pdev->irq;
 
+       /* bjoern: We need to tell the card to enable interrupts, in
+          case the serial eprom didn't do this already.  See the
+          PLX9052 data book, p8-1 and 8-24 for reference. */
+       csr_reg = inl(plx_addr + PLX_INTCSR);
+       if (!(csr_reg & PLX_INTCSR_INTEN)) {
+               csr_reg |= PLX_INTCSR_INTEN;
+               outl(csr_reg, plx_addr + PLX_INTCSR);
+               csr_reg = inl(plx_addr + PLX_INTCSR);
+               if (!(csr_reg & PLX_INTCSR_INTEN)) {
+                       printk(KERN_ERR PFX "Cannot enable interrupts\n");
+                       goto fail;
+               }
+       }
+
+       err = orinoco_plx_cor_reset(priv);
+       if (err) {
+               printk(KERN_ERR PFX "Initial reset failed\n");
+               goto fail;
+       }
+
+       printk(KERN_DEBUG PFX "CIS: ");
+       for (i = 0; i < 16; i++) {
+               printk("%02X:", readb(attr_mem + 2*i));
+       }
+       printk("\n");
+
+       /* Verify whether a supported PC card is present */
+       /* FIXME: we probably need to be smarted about this */
+       for (i = 0; i < sizeof(cis_magic); i++) {
+               if (cis_magic[i] != readb(attr_mem +2*i)) {
+                       printk(KERN_ERR PFX "The CIS value of Prism2 PC "
+                              "card is unexpected\n");
+                       err = -EIO;
+                       goto fail;
+               }
+       }
+
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot register network device\n");
@@ -277,13 +318,21 @@
        return 0;
 
  fail:
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
+
  fail_irq:
+       pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
+
  fail_alloc:
        pci_iounmap(pdev, mem);
- fail_map:
-       release_region(pccard_ioaddr, pccard_iolen);
+
+ fail_map_io:
+       iounmap(attr_mem);
+
+ fail_map_attr:
+       pci_release_regions(pdev);
+
  fail_resources:
        pci_disable_device(pdev);
 
@@ -294,20 +343,18 @@
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_plx_card *card = priv->card;
+       u8 __iomem *attr_mem = card->attr_mem;
 
-       unregister_netdev(dev);
-               
-       if (dev->irq)
-               free_irq(dev->irq, dev);
+       BUG_ON(! dev);
 
-       pci_iounmap(pdev, priv->hw.iobase);
-               
+       unregister_netdev(dev);
+       free_irq(dev->irq, dev);
        pci_set_drvdata(pdev, NULL);
-
        free_orinocodev(dev);
-
-       release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
-
+       pci_iounmap(pdev, priv->hw.iobase);
+       iounmap(attr_mem);
+       pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 
Index: working-2.6/drivers/net/wireless/orinoco_tmd.c
===================================================================
--- working-2.6.orig/drivers/net/wireless/orinoco_tmd.c 2005-01-12 
15:47:48.216477768 +1100
+++ working-2.6/drivers/net/wireless/orinoco_tmd.c      2004-11-05 
14:37:35.000000000 +1100
@@ -79,59 +79,89 @@
 #include "orinoco.h"
 
 #define COR_VALUE      (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with 
interrupt in level trigger */
+#define COR_RESET     (0x80)   /* reset bit in the COR register */
+#define TMD_RESET_TIME (500)   /* milliseconds */
+
+/* Orinoco TMD specific data */
+struct orinoco_tmd_card {
+       u32 tmd_io;
+};
+
+
+/*
+ * Do a soft reset of the card using the Configuration Option Register
+ */
+static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
+{
+       hermes_t *hw = &priv->hw;
+       struct orinoco_tmd_card *card = priv->card;
+       u32 addr = card->tmd_io;
+       unsigned long timeout;
+       u16 reg;
+
+       outb(COR_VALUE | COR_RESET, addr);
+       mdelay(1);
+
+       outb(COR_VALUE, addr);
+       mdelay(1);
+
+       /* Just in case, wait more until the card is no longer busy */
+       timeout = jiffies + (TMD_RESET_TIME * HZ / 1000);
+       reg = hermes_read_regn(hw, CMD);
+       while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
+               mdelay(1);
+               reg = hermes_read_regn(hw, CMD);
+       }
+
+       /* Did we timeout ? */
+       if (reg & HERMES_CMD_BUSY) {
+               printk(KERN_ERR PFX "Busy timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 
 static int orinoco_tmd_init_one(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
        int err = 0;
-       u32 reg, addr;
        struct orinoco_private *priv = NULL;
-       unsigned long pccard_ioaddr = 0;
-       unsigned long pccard_iolen = 0;
+       struct orinoco_tmd_card *card;
        struct net_device *dev = NULL;
        void __iomem *mem;
 
        err = pci_enable_device(pdev);
        if (err) {
                printk(KERN_ERR PFX "Cannot enable PCI device\n");
-               return -EIO;
+               return err;
        }
 
-       printk(KERN_DEBUG PFX "TMD setup\n");
-       pccard_ioaddr = pci_resource_start(pdev, 2);
-       pccard_iolen = pci_resource_len(pdev, 2);
-       if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
-               printk(KERN_ERR PFX "I/O resource at 0x%lx len 0x%lx busy\n",
-                       pccard_ioaddr, pccard_iolen);
-               err = -EBUSY;
-               goto out;
+       err = pci_request_regions(pdev, DRIVER_NAME);
+       if (err != 0) {
+               printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+               goto fail_resources;
        }
-       addr = pci_resource_start(pdev, 1);
-       outb(COR_VALUE, addr);
-       mdelay(1);
-       reg = inb(addr);
-       if (reg != COR_VALUE) {
-               printk(KERN_ERR PFX "Error setting TMD COR values %x should be 
%x\n", reg, COR_VALUE);
-               err = -EIO;
-               goto out2;
+
+       mem = pci_iomap(pdev, 2, 0);
+       if (! mem) {
+               err = -ENOMEM;
+               goto fail_iomap;
        }
 
        /* Allocate network device */
-       dev = alloc_orinocodev(0, NULL);
+       dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
        if (! dev) {
                printk(KERN_ERR PFX "Cannot allocate network device\n");
                err = -ENOMEM;
-               goto out2;
-       }
-
-       mem = pci_iomap(pdev, 2, 0);
-       if (!mem) {
-               err = -ENOMEM;
-               goto out3;
+               goto fail_alloc;
        }
 
        priv = netdev_priv(dev);
-       dev->base_addr = pccard_ioaddr;
+       card = priv->card;
+       card->tmd_io = pci_resource_start(pdev, 1);
+       dev->base_addr = pci_resource_start(pdev, 2);
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
@@ -140,36 +170,46 @@
 
        printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
               "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
-              pccard_ioaddr);
+              dev->base_addr);
 
        err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
                          dev->name, dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
                err = -EBUSY;
-               goto out4;
+               goto fail_irq;
        }
        dev->irq = pdev->irq;
 
+       err = orinoco_tmd_cor_reset(priv);
+       if (err) {
+               printk(KERN_ERR PFX "Initial reset failed\n");
+               goto fail;
+       }
+
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot register network device\n");
-               goto out5;
+               goto fail;
        }
 
        return 0;
 
-out5:
-       free_irq(dev->irq, dev);
-out4:
-       pci_iounmap(pdev, mem);
-out3:
+ fail:
+       free_irq(pdev->irq, dev);
+
+ fail_irq:
+       pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
-out2:
-       release_region(pccard_ioaddr, pccard_iolen);
-out:
+
+ fail_alloc:
+       pci_iounmap(pdev, mem);
+
+ fail_iomap:
+       pci_release_regions(pdev);
+
+ fail_resources:
        pci_disable_device(pdev);
-       printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
 
        return err;
 }
@@ -177,21 +217,16 @@
 static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = dev->priv;
 
-       unregister_netdev(dev);
-               
-       if (dev->irq)
-               free_irq(dev->irq, dev);
-
-       pci_iounmap(pdev, priv->hw.iobase);
+       BUG_ON(! dev);
 
+       unregister_netdev(dev);
+       free_irq(dev->irq, dev);
        pci_set_drvdata(pdev, NULL);
-
        free_orinocodev(dev);
-
-       release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));
-
+       pci_iounmap(pdev, priv->hw.iobase);
+       pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 


-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist.  NOT _the_ _other_ _way_
                                | _around_!
http://www.ozlabs.org/people/dgibson


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click


Ruby Jobs
Java Jobs
Jobs in California
more...
what
job title, keywords
where
city, state, zip
jobs by job search
Search:
Java, servers, webhosting, windows, cisco ...
more...
<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

Recently Viewed:
encryption.gpg....    ietf.rfc822/199...    freebsd.devel.i...    lang.haskell.li...    mail.squirrelma...    web.zope.plone....    yellowdog.gener...    text.xml.xalan....    recreation.phot...    kde.devel.educa...    hardware.bus.ca...    printing.ghosts...    voip.peering/20...    assembly/2006-0...    org.user-groups...    culture.interne...    network.i2p/200...    boot-loaders.ya...    xfree86.render/...    qnx.openqnx.dev...    jakarta.velocit...    user-groups.pal...   
Home | blog view | USPTO Patent Archive | advertise | OSDir is an inevitable website. super tiny logo

Free Magazines

Cisco News
Receive a free quarterly e-newsletter with exclusive articles on how Cisco IT uses its own products and solutions to enable the business.
subscribe

Systems Management News, the newspaper for IT systems administration and data center managers! Each issue of Systems Management News is chock-full of news and analysis to help you understand what's happening in your field.
subscribe

The Enterprise Newsweekly eWeek is the essential technology information source for builders of e-business.
subscribe

Oracle Magazine Oracle Magazine contains technology strategy articles, sample code, tips, Oracle and partner news, how to articles for developers and DBAs, and more. Oracle (NASDAQ: ORCL) is the world's largest enterprise software company.
subscribe

Total Telecom Total Telecom is "The Economist of the communications industry".
subscribe