Beispiel #1
0
//___________________________________________________________________________________________
long EvtUnlockedIoDeviceControl(struct file*  filep, unsigned int cmd, unsigned long arg)
{
   int iTimeoutMs, iSize;  //used by interrupt and record
   DeviceContext *d = filep->private_data;

   switch(cmd)
   {
      case 'r': //get record, arg contains pointer to buffer containing timeout and size, and arg returns pointer to record
         if( copy_from_user(&iSize, (int*)arg, sizeof(iSize)) )	//get data from user space in arg (e.g. 1000) and copy to kernel buffer (iTimeoutMs)
            return -EFAULT;

         if( copy_from_user(&iTimeoutMs, (int*) (arg + sizeof(iSize)), sizeof(iTimeoutMs)) )	//get data from user space in arg (e.g. 1000) and copy to kernel buffer (iTimeoutMs)
            return -EFAULT;

         if     (iTimeoutMs  > 0) //positive timeout
            wait_event_interruptible_timeout(d->recordWaitQ, d->recordQ.in != d->recordQ.out, iTimeoutMs * HZ / 1000); //wait up to the timeout for the IRQ byte to be set by the IRQ handler (wait for the circular buffer to be non-empty)
         else if(iTimeoutMs < 0)  //negative timeout (timeout disabled)
            wait_event_interruptible(d->recordWaitQ, d->recordQ.in != d->recordQ.out); //wait forever

         if(d->recordQ.in != d->recordQ.out) //q non empty
         {
            if(copy_to_user((char*)arg, d->recordQ.q[ d->recordQ.out ], iSize))	//return the record retrieved in the interrupt handler to users space in arg
               return -EFAULT;

            d->recordQ.out = (d->recordQ.out + 1) % SIZE;  //increment the read pointer
         }
         else //wait_event was interrupted by a signal (e.g. ctrl-c) < 0, or timeout = 0
            return -ERESTARTSYS;  //user mode ioctl returns -1

         break;

      case 'i': //interrupt (get EI/UI status byte).  arg contains pointer to timeout, and arg returns pointer to status byte
         if( copy_from_user(&iTimeoutMs, (int*)arg, sizeof(iTimeoutMs)) )	//get data from user space in arg (e.g. 1000) and copy to kernel buffer (iTimeoutMs)
            return -EFAULT;

         if     (iTimeoutMs  > 0) //positive timeout
            wait_event_interruptible_timeout(d->interruptWaitQ, d->interruptQ.in != d->interruptQ.out, iTimeoutMs * HZ / 1000); //wait up to the timeout for the IRQ byte to be set by the IRQ handler (wait for the circular buffer to be non-empty)
         else if(iTimeoutMs < 0)  //negative timeout (timeout disabled)
            wait_event_interruptible(d->interruptWaitQ, d->interruptQ.in != d->interruptQ.out); //wait forever

         if(d->interruptQ.in != d->interruptQ.out) //q non empty
         {
            if(copy_to_user((int*)arg, &(d->interruptQ.q[ d->interruptQ.out ]), sizeof(unsigned char)))	//return the status byte retrieved in the interrupt handler to users space in arg
               return -EFAULT;

            d->interruptQ.out = (d->interruptQ.out + 1) % SIZE;  //increment the read pointer
         }
         else //wait_event was interrupted by a signal (e.g. ctrl-c) < 0, or timeout = 0
            return -ERESTARTSYS;  //user mode ioctl returns -1

         break;

      case 'R': //reset DMC-18x0/6
         if(d->pciInfo.m_fSubSystem == DMC18x6) //18x6 (do nothing on 18x2)
            outb(0x80, d->baseAddress + 8); //reset 18x6
      break;

			case 'v':
				printk(KERN_INFO "GalilIoctl IOCTL_GALIL_VERSION\n");
				if (copy_to_user((char*)arg, "galiltools", strlen("galiltools")))
					return -EACCES;
				break;

      default:
         return -ENOTTY; //invalid ioctl code (switch fell thru).  POSIX says we should return -ENOTTY instead of EINVAL      
   }

   return 0; //normal 
}
Beispiel #2
0
static inline void
fWrite_hfc8(hfc4s8s_hw *a, u_char c)
{
	outb(c, a->iobase);
}
Beispiel #3
0
void	pic_send_eoi(unsigned char irq)
{
	outb(PIC1_COMMAND, PIC_EOI);
	if (irq >= 32 + 8)
		outb(PIC2_COMMAND, PIC_EOI);
}
Beispiel #4
0
static void ide_outb (u8 val, unsigned long port)
{
	outb(val, port);
}
Beispiel #5
0
/* inline functions io mapped */
static inline void
SetRegAddr(hfc4s8s_hw *a, u_char b)
{
	outb(b, (a->iobase) + 4);
}
Beispiel #6
0
PUBLIC void irq_8259_mask(const int irq)
{
	const unsigned ctl_mask = irq < 8 ? INT_CTLMASK : INT2_CTLMASK;
	outb(ctl_mask, inb(ctl_mask) | (1 << (irq & 0x7)));
}
Beispiel #7
0
Datei: cga.c Projekt: CoryXie/NxM
static uchar
cgaregr(int index)
{
	outb(0x3D4, index);
	return inb(0x3D4+1) & 0xFF;
}
Beispiel #8
0
static void quirk_wakeup_oxsemi(struct pcmcia_device *link)
{
    struct serial_info *info = link->priv;

    outb(12, info->c950ctrl + 1);
}
Beispiel #9
0
/**
 * host_control_smi: generate host control SMI
 *
 * Caller must set up the host control command in smi_data_buf.
 */
static int host_control_smi(void)
{
	struct apm_cmd *apm_cmd;
	u8 *data;
	unsigned long flags;
	u32 num_ticks;
	s8 cmd_status;
	u8 index;

	apm_cmd = (struct apm_cmd *)smi_data_buf;
	apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;

	switch (host_control_smi_type) {
	case HC_SMITYPE_TYPE1:
		spin_lock_irqsave(&rtc_lock, flags);
		/* write SMI data buffer physical address */
		data = (u8 *)&smi_data_buf_phys_addr;
		for (index = PE1300_CMOS_CMD_STRUCT_PTR;
		     index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
		     index++, data++) {
			outb(index,
			     (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
			outb(*data,
			     (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
		}

		/* first set status to -1 as called by spec */
		cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
		outb((u8) cmd_status, PCAT_APM_STATUS_PORT);

		/* generate SMM call */
		outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
		spin_unlock_irqrestore(&rtc_lock, flags);

		/* wait a few to see if it executed */
		num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
		while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
		       == ESM_STATUS_CMD_UNSUCCESSFUL) {
			num_ticks--;
			if (num_ticks == EXPIRED_TIMER)
				return -ETIME;
		}
		break;

	case HC_SMITYPE_TYPE2:
	case HC_SMITYPE_TYPE3:
		spin_lock_irqsave(&rtc_lock, flags);
		/* write SMI data buffer physical address */
		data = (u8 *)&smi_data_buf_phys_addr;
		for (index = PE1400_CMOS_CMD_STRUCT_PTR;
		     index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
		     index++, data++) {
			outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
			outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
		}

		/* generate SMM call */
		if (host_control_smi_type == HC_SMITYPE_TYPE3)
			outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
		else
			outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);

		/* restore RTC index pointer since it was written to above */
		CMOS_READ(RTC_REG_C);
		spin_unlock_irqrestore(&rtc_lock, flags);

		/* read control port back to serialize write */
		cmd_status = inb(PE1400_APM_CONTROL_PORT);

		/* wait a few to see if it executed */
		num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
		while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
			num_ticks--;
			if (num_ticks == EXPIRED_TIMER)
				return -ETIME;
		}
		break;

	default:
		dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
			__func__, host_control_smi_type);
		return -ENOSYS;
	}

	return 0;
}
int __devinit
setup_hfcs(struct IsdnCard *card)
{
	struct IsdnCardState *cs = card->cs;
	char tmp[64];

	strcpy(tmp, hfcs_revision);
	printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));

#ifdef __ISAPNP__
	if (!card->para[1] && isapnp_present()) {
		struct pnp_dev *pnp_d;
		while(ipid->card_vendor) {
			if ((pnp_c = pnp_find_card(ipid->card_vendor,
				ipid->card_device, pnp_c))) {
				pnp_d = NULL;
				if ((pnp_d = pnp_find_dev(pnp_c,
					ipid->vendor, ipid->function, pnp_d))) {
					int err;

					printk(KERN_INFO "HiSax: %s detected\n",
						(char *)ipid->driver_data);
					pnp_disable_dev(pnp_d);
					err = pnp_activate_dev(pnp_d);
					if (err<0) {
						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
							__func__, err);
						return(0);
					}
					card->para[1] = pnp_port_start(pnp_d, 0);
					card->para[0] = pnp_irq(pnp_d, 0);
					if (!card->para[0] || !card->para[1]) {
						printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
							card->para[0], card->para[1]);
						pnp_disable_dev(pnp_d);
						return(0);
					}
					break;
				} else {
					printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
				}
			}
			ipid++;
			pnp_c = NULL;
		} 
		if (!ipid->card_vendor) {
			printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
			return(0);
		}
	}
#endif
	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
	cs->irq = card->para[0];
	cs->hw.hfcD.cip = 0;
	cs->hw.hfcD.int_s1 = 0;
	cs->hw.hfcD.send = NULL;
	cs->bcs[0].hw.hfc.send = NULL;
	cs->bcs[1].hw.hfc.send = NULL;
	cs->hw.hfcD.dfifosize = 512;
	cs->dc.hfcd.ph_state = 0;
	cs->hw.hfcD.fifo = 255;
	if (cs->typ == ISDN_CTYPE_TELES3C) {
		cs->hw.hfcD.bfifosize = 1024 + 512;
	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
		cs->hw.hfcD.bfifosize = 7*1024 + 512;
	} else
		return (0);
	if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) {
		printk(KERN_WARNING
		       "HiSax: %s config port %x-%x already in use\n",
		       CardType[card->typ],
		       cs->hw.hfcD.addr,
		       cs->hw.hfcD.addr + 2);
		return (0);
	}
	printk(KERN_INFO
	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
	       cs->hw.hfcD.addr,
	       cs->irq, HZ);
	if (cs->typ == ISDN_CTYPE_TELES3C) {
		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
		outb(0x00, cs->hw.hfcD.addr);
		outb(0x56, cs->hw.hfcD.addr | 1);
	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
		/* Acer P10 IO ADR is 0x300 */
		outb(0x00, cs->hw.hfcD.addr);
		outb(0x57, cs->hw.hfcD.addr | 1);
	}
	set_cs_func(cs);
	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
	cs->hw.hfcD.timer.data = (long) cs;
	init_timer(&cs->hw.hfcD.timer);
	cs->cardmsg = &hfcs_card_msg;
	cs->irq_func = &hfcs_interrupt;
	return (1);
}
Beispiel #11
0
void pci_config_write8(uint32_t pci_addr, uint8_t reg, uint8_t data)
{
	pci_addr |= reg & ~3;
	outl(PCI_ADDR_REG, pci_addr);
	outb(PCI_DATA_REG + (reg & 3), data);
}
Beispiel #12
0
unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
	unsigned short w_EepromStartAddress)
{

	unsigned char b_Counter = 0;

	unsigned char b_ReadByte = 0;

	unsigned char b_ReadLowByte = 0;

	unsigned char b_ReadHighByte = 0;

	unsigned char b_SelectedAddressLow = 0;

	unsigned char b_SelectedAddressHigh = 0;

	unsigned short w_ReadWord = 0;

	/**************************/

	/* Test the PCI chip type */

	/**************************/

	if ((!strcmp(pc_PCIChipInformation, "S5920")) ||
		(!strcmp(pc_PCIChipInformation, "S5933")))
	{

		for (b_Counter = 0; b_Counter < 2; b_Counter++)
		{

			b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256;	/* Read the low 8 bit part */

			b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256;	/* Read the high 8 bit part */

	      /************************************/

			/* Select the load low address mode */

	      /************************************/

			outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F);

	      /****************/

			/* Wait on busy */

	      /****************/

			v_EepromWaitBusy(w_PCIBoardEepromAddress);

	      /************************/

			/* Load the low address */

	      /************************/

			outb(b_SelectedAddressLow,
				w_PCIBoardEepromAddress + 0x3E);

	      /****************/

			/* Wait on busy */

	      /****************/

			v_EepromWaitBusy(w_PCIBoardEepromAddress);

	      /*************************************/

			/* Select the load high address mode */

	      /*************************************/

			outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F);

	      /****************/

			/* Wait on busy */

	      /****************/

			v_EepromWaitBusy(w_PCIBoardEepromAddress);

	      /*************************/

			/* Load the high address */

	      /*************************/

			outb(b_SelectedAddressHigh,
				w_PCIBoardEepromAddress + 0x3E);

	      /****************/

			/* Wait on busy */

	      /****************/

			v_EepromWaitBusy(w_PCIBoardEepromAddress);

	      /************************/

			/* Select the READ mode */

	      /************************/

			outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F);

	      /****************/

			/* Wait on busy */

	      /****************/

			v_EepromWaitBusy(w_PCIBoardEepromAddress);

	      /*****************************/

			/* Read data into the EEPROM */

	      /*****************************/

			b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E);

	      /****************/

			/* Wait on busy */

	      /****************/

			v_EepromWaitBusy(w_PCIBoardEepromAddress);

	      /*********************************/

			/* Select the upper address part */

	      /*********************************/

			if (b_Counter == 0)
			{

				b_ReadLowByte = b_ReadByte;

			}	/*  if(b_Counter==0) */

			else
			{

				b_ReadHighByte = b_ReadByte;

			}	/*  if(b_Counter==0) */

		}		/*  for (b_Counter=0; b_Counter<2; b_Counter++) */

		w_ReadWord = (b_ReadLowByte | (((unsigned short) b_ReadHighByte) * 256));

	}			/*  end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) */

	if (!strcmp(pc_PCIChipInformation, "93C76"))
	{

	   /*************************************/

		/* Read 16 bit from the EEPROM 93C76 */

	   /*************************************/

		v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress,
			&w_ReadWord);

	}

	return w_ReadWord;

}
Beispiel #13
0
static int __devinit EvtDevicePrepareHardware(struct pci_dev  *pdev, const struct pci_device_id  *ent)
{
   int ret = -EIO;
   u16 subVender;
   u16 uModel;    //will contain galil model number (e.g. 0x1802)
	long resourceStart, resourceEnd, resourceLen;
   char name[10]; //will contain name in /dev/ (e.g. galilpci0)
   device++;      //incremented each time be find a galil board
   
   if (device >= MAX_DEVICES) {
      printk("EvtDevicePrepareHardware This driver only supports %i devices\n", MAX_DEVICES);
      device--; //update the device count
      return -ENODEV;
   }
   
   if (pci_enable_device(pdev)) {  //wake up the device
      printk("EvtDevicePrepareHardware Not possible to enable PCI Device\n");
      device--; //update the device count
      return -ENODEV;
   }

   //Mark all PCI regions associated with PCI device pdev as being reserved by owner res_name.
   //Do not access any address inside the PCI regions unless this call returns successfully.
   //This will reverve both i/o ports and memory regions, and shows up in /proc/ioports and /proc/iomem
   if (pci_request_regions(pdev, GALILNAME)) {
      printk("EvtDevicePrepareHardware I/O address (0x%04x) already in use\n", (unsigned int) d[device].baseAddress);
      device--; //update the device count
      return -ENODEV;
   }
   
   //I/O ADDRESSES
   d[device].baseAddress   = pci_resource_start(pdev, /*BAR*/ 2); //get base address N from BAR2
   d[device].irqAddress    = pci_resource_start(pdev, /*BAR*/ 1); //get base address N from BAR2.  0 on 18x0/2.  Non zero on 18x2.
   resourceStart = pci_resource_start(pdev, /*BAR*/ 0); 
	if ( resourceStart == 0x0000 )
	{
		printk("No data record channel\n");
		resourceEnd = 0;
		resourceLen = 0;
	} else
	{
		resourceEnd = pci_resource_end(pdev, /*BAR*/ 0); 
		resourceLen = resourceEnd-resourceStart+1;
	}
	printk("Bar 0 address: 0x%X to 0x%X, len=%i\n", resourceStart, resourceEnd, resourceLen);

	if ( resourceLen == 128 )
	{
//	   d[device].recordAddress = pci_iomap(pdev, /*BAR*/ 0, 128 /*bytes*/);
		d[device].pciInfo.m_fRevsion = REV1; // PLX based device
		d[device].recordAddress = resourceStart;
		printk("PLX based controller - not supported\n");
      device--; //update the device count
      return -ENODEV;
	} else if ( resourceLen == 512 )
	{
		d[device].pciInfo.m_fRevsion = REV2; // XININX based device
		d[device].recordAddress = pci_iomap(pdev, 0, 512);
		printk("XINUNX based controller\n");
	}

   if (d[device].baseAddress == 0x0000) { //check base address.
      printk("EvtDevicePrepareHardware No Main I/O-Address for device detected\n");
      ret = -ENODEV;
      goto release_regions;
   }
   printk("Base Address: 0x%X\n", d[device].baseAddress);
   printk("Record Address: 0x%X\n", d[device].recordAddress);

   // Identify PCI device
   pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subVender);    //read galil model (e.g. 0x1806)
   pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &uModel);    //read galil model (e.g. 0x1806)
   d[device].pciInfo.m_fSubVendor = subVender;
   d[device].pciInfo.m_fSubSystem = uModel;
   
  //register the device under major number 10.  Minor number will show up in /proc/misc
   d[device].galilpci_miscdev.minor  = MISC_DYNAMIC_MINOR, //assign the minor number dynamically (ask for a free one).  This field will eventually contain the actual minor number.
   sprintf(name, GALILNAME "%i", device);
   d[device].galilpci_miscdev.name   = name,               //the name for this device, meant for human consumption: users will find the name in the /proc/misc file.
   d[device].galilpci_miscdev.fops   = &galilpci_fops,     //the file operations
   d[device].bOpen = 0;                                    //file not open

   ret = misc_register(&(d[device].galilpci_miscdev));
   if (ret) {
      printk ("EvtDevicePrepareHardware cannot register miscdev (err=%d)\n", ret);
      goto release_regions;
   }
   
   init_waitqueue_head(&d[device].sleepQ);

   //INTERRUPTS
   d[device].interrupt = pdev->irq; //store the IRQ number so we can call free-irq in the cleanup function when the module us removed with rmmod
   if (request_irq(d[device].interrupt, EvtInterruptIsr, IRQF_SHARED, GALILNAME, &d[device])) //register the interrupt handler.  This should happen before we enable interrupts on the controller.  Kernel 2.6.18 2006Sep changed SA_SHIRQ to IRQF_SHARED http://lwn.net/Articles/2.6-kernel-api/
   {
      printk("EvtDevicePrepareHardware IRQ %x is not free\n", d[device].interrupt);
      goto misc_deregister;
   }

   init_waitqueue_head(&d[device].interruptWaitQ);         //initialize the list of processes waiting for EI/UI interrupts
   d[device].interruptQ.in = d[device].interruptQ.out = 0; //initialize circular buffer pointers

   init_waitqueue_head(&d[device].recordWaitQ);            //initialize the list of processes waiting for record interrupts
   d[device].recordQ.in    = d[device].recordQ.out    = 0; //initialize circular buffer pointers

   //ENABLE INTERRUPTS ON CONTROLLER
#if 1
	switch (d[device].pciInfo.m_fSubSystem)
	{
	case DMC18x2:
      inb(       d[device].baseAddress + 1);  //reset 4701 ("clear FIFOs").  Interrupts won't enable on 18x2 rev F without this (rev D1 doesn't require it)
      outb(0x01, d[device].baseAddress + 1);
      outb(0x80, d[device].baseAddress + 1);
      outb(0x01, d[device].baseAddress + 1);
      outb(0x80, d[device].baseAddress + 1);
      inb(       d[device].baseAddress + 1);

      outb(0x02, d[device].baseAddress + 1);  //set 4701 pointer register to point to the interrupt mask register (register 2)    
      outb(0x04, d[device].baseAddress + 1);  //interrupt when the controller writes to its mailbox (don't interrupt on 6 full, 5 empty, 4 almost full, 3 almost empty, 1 byte detect, nor 0 parity/frame error
      //below is necessary so 18x2 doesn't keep interrupting
      outb(0x06, d[device].baseAddress + 1);  //set 4701 pointer register to point to the other port's mailbox
      inb (      d[device].baseAddress + 1);  //read other port's mailbox (clears any pending mailbox interrupt)

      d[device].irqAddress += 0x4c;           //76 byte offset from the address in BAR1
      outl( 0x40 | inl(d[device].irqAddress), d[device].irqAddress); //enable interrupts on the controller.  They will stay enabled until the module is unloaded (or power is shut off)
		break;
	case DMC18x6:
	case DMC18x0:
      outb(0x40 | inb(d[device].baseAddress + 4), d[device].baseAddress + 4); //enable interrupts on the controller.  They will stay enabled until the module is unloaded (or power is shut off)
		break;
	case DMC1417:
		d[device].irqAddress += 0x4c;
		outb(0x40 | inb(d[device].irqAddress), d[device].irqAddress); //enable interrupts on the controller.  They will stay enabled until the module is unloaded (or power is shut off)
		break;
	case DMC1640:
	default:
		;
	};
#else
   if(d[device].irqAddress) //18x2
   {
      inb(       d[device].baseAddress + 1);  //reset 4701 ("clear FIFOs").  Interrupts won't enable on 18x2 rev F without this (rev D1 doesn't require it)
      outb(0x01, d[device].baseAddress + 1);
      outb(0x80, d[device].baseAddress + 1);
      outb(0x01, d[device].baseAddress + 1);
      outb(0x80, d[device].baseAddress + 1);
      inb(       d[device].baseAddress + 1);

      outb(0x02, d[device].baseAddress + 1);  //set 4701 pointer register to point to the interrupt mask register (register 2)    
      outb(0x04, d[device].baseAddress + 1);  //interrupt when the controller writes to its mailbox (don't interrupt on 6 full, 5 empty, 4 almost full, 3 almost empty, 1 byte detect, nor 0 parity/frame error
      //below is necessary so 18x2 doesn't keep interrupting
      outb(0x06, d[device].baseAddress + 1);  //set 4701 pointer register to point to the other port's mailbox
      inb (      d[device].baseAddress + 1);  //read other port's mailbox (clears any pending mailbox interrupt)

      d[device].irqAddress += 0x4c;           //76 byte offset from the address in BAR1
      outl( 0x40 | inl(d[device].irqAddress), d[device].irqAddress); //enable interrupts on the controller.  They will stay enabled until the module is unloaded (or power is shut off)
   }
   else //18x6   
      outb(0x40 | inb(d[device].baseAddress + 4), d[device].baseAddress + 4); //enable interrupts on the controller.  They will stay enabled until the module is unloaded (or power is shut off)
#endif

   printk("EvtDevicePrepareHardware I/O address (0x%lx), Model %x, minor number %d Rev(%i)\n", 
		d[device].baseAddress, uModel, d[device].galilpci_miscdev.minor, d[device].pciInfo.m_fRevsion);

   return 0;

misc_deregister:   misc_deregister(&(d[device].galilpci_miscdev));  //unregister the device with major number 10  
release_regions:   pci_release_regions(pdev);
disable_device:    pci_disable_device(pdev);
   device--; //update the device count
   return ret;
}
Beispiel #14
0
//___________________________________________________________________________________________
static irqreturn_t EvtInterruptIsr(int irq, void *dev_id) // struct pt_regs *regs)  //Kernel 2.6.19 removed regs argument http://lwn.net/Articles/202449/
{
	unsigned char flagByte;
   unsigned char statusByte;  DeviceContext *d = dev_id; //get a pointer to the device.  This was passed to request_irq()
	int dataRecordSize;

#if 1
	switch(d->pciInfo.m_fSubSystem)
	{
	case DMC18x2:
      if(0x45 == (inl(d->irqAddress) & 0x45)) //this is our interrupt (bit 0 local interrupts enabled, bit 2 status (our)s, bit 6 enable (set below))
      {
         unsigned char status = inb(d->baseAddress + 1); //read 4701 status register (clear 4701 IRQ flag)

         if(status & 0x04) //bit 2 means mailbox interrupt (controller sending status byte to PC)
         {
            outb(0x06, d->baseAddress + 1);   //write 6 to N+1 (set 4701 pointer register to point to other port's mailbox)
            statusByte = inb(d->baseAddress + 1); //read status byte (4701 other port's mailbox)
         } else //controller probably set MR bit (bit 7) of 4701 (by hard resetting controller)
         {
            outb(0x02, d->baseAddress + 1);  //set 4701 pointer register to point to the interrupt mask register (register 2)    
            outb(0x04, d->baseAddress + 1);  //interrupt when the controller writes to its mailbox (don't interrupt on 6 full, 5 empty, 4 almost full, 3 almost empty, 1 byte detect, nor 0 parity/frame error
            //below is necessary so 18x2 doesn't keep interrupting
            outb(0x06, d->baseAddress + 1);  //set 4701 pointer register to point to the other port's mailbox
            inb(d->baseAddress + 1);         //read other port's mailbox (clears any pending mailbox interrupt)
	         return IRQ_HANDLED; //Tell WDF, and hence Windows, that there WAS an interrupt outstanding for us to process
         }
      } else
      	return IRQ_NONE;
		break;
	case DMC18x6:
      if(0x60 == (inb(d->baseAddress + 4) & 0x60)) //if the Galil controller generated an interrupt and interrupts were enabled on the controller
      {
         statusByte = inb(d->baseAddress + 8); //read status byte (must happen before acknowledging the interrupt below)
         outb(0x20 | inb(d->baseAddress + 4), d->baseAddress + 4); //acknowledge the interrupt (else the controller will keep interrupting)       
      } else
      	return IRQ_NONE;
		break;
	case DMC1640:
	case DMC18x0:
		flagByte = inb(d->baseAddress + 4);
		if ( d->pciInfo.m_fRevsion == REV1 )
		{
	      if(0x60 == (flagByte & 0x60)) //if the Galil controller generated an interrupt and interrupts were enabled on the controller
	      {
	         statusByte = inb(d->baseAddress + 8); //read status byte (must happen before acknowledging the interrupt below)
	         outb(flagByte, d->baseAddress + 4); //acknowledge the interrupt (else the controller will keep interrupting)       
	      } else
	      	return IRQ_NONE;
		} else
		{
	      if(0x60 == (flagByte & 0x60)) //if the Galil controller generated an interrupt and interrupts were enabled on the controller
	      {
	         statusByte = inb(d->baseAddress + 8); //read status byte (must happen before acknowledging the interrupt below)
	         outb(0x20 | flagByte, d->baseAddress + 4); //acknowledge the interrupt (else the controller will keep interrupting)       
	      } else
	      	return IRQ_NONE;
		}
	break;
	case DMC1417:
		if(0x45 == (inb(d->irqAddress) & 0x45))
		{
			statusByte = 0xFF; // 1417 interrupt need to be read via IV command
			outb(0x05, d->irqAddress + 1); // stop Interrupt
		} else 
			return IRQ_NONE;
		break;
	default:
		;
	};
#else
   if(d->irqAddress) //18x2
   {
      if(0x45 == (inl(d->irqAddress) & 0x45)) //this is our interrupt (bit 0 local interrupts enabled, bit 2 status (our)s, bit 6 enable (set below))
      {
         unsigned char status = inb(d->baseAddress + 1); //read 4701 status register (clear 4701 IRQ flag)

         if(status & 0x04) //bit 2 means mailbox interrupt (controller sending status byte to PC)
         {
            outb(0x06, d->baseAddress + 1);   //write 6 to N+1 (set 4701 pointer register to point to other port's mailbox)
            statusByte = inb(d->baseAddress + 1); //read status byte (4701 other port's mailbox)
            goto DPC;
         }
         else //controller probably set MR bit (bit 7) of 4701 (by hard resetting controller)
         {
            outb(0x02, d->baseAddress + 1);  //set 4701 pointer register to point to the interrupt mask register (register 2)    
            outb(0x04, d->baseAddress + 1);  //interrupt when the controller writes to its mailbox (don't interrupt on 6 full, 5 empty, 4 almost full, 3 almost empty, 1 byte detect, nor 0 parity/frame error
            //below is necessary so 18x2 doesn't keep interrupting
            outb(0x06, d->baseAddress + 1);  //set 4701 pointer register to point to the other port's mailbox
            inb(d->baseAddress + 1);         //read other port's mailbox (clears any pending mailbox interrupt)
         }

         return IRQ_HANDLED; //Tell WDF, and hence Windows, that there WAS an interrupt outstanding for us to process
      }
   }
   else //18x6
   {
      if(0x60 == (inb(d->baseAddress + 4) & 0x60)) //if the Galil controller generated an interrupt and interrupts were enabled on the controller
      {
         statusByte = inb(d->baseAddress + 8); //read status byte (must happen before acknowledging the interrupt below)
         outb(0x20 | inb(d->baseAddress + 4), d->baseAddress + 4); //acknowledge the interrupt (else the controller will keep interrupting)       
         goto DPC;
      }
   }
   return IRQ_NONE; //not our interrupt, another device sharing the IRQ generated the interrupt    

DPC: 

#endif

//   printk("EvtInterruptIsr 0x%X\n", statusByte);
   switch(statusByte)
   {
      case 0xBA: break; //command done (colon sent)
      case 0xBB: break; //MG
      case 0xBC:        //record
      	
         if( (d->recordAddress != 0) && (d->recordQ.out != (d->recordQ.in + 1) % SIZE) ) //circular buffer NOT FULL (will lose new status bytes if full--old ones are retained)
         {
				if ( d->pciInfo.m_fRevsion == REV2 )
   	         memcpy_fromio(d->recordQ.q[ d->recordQ.in ], (void __iomem *)d->recordAddress, 512); //copy 512 bytes from the dual port RAM
				else
				{
					dataRecordSize = 0;
					memset(d->recordQ.q[ d->recordQ.in ], 0, sizeof(d->recordQ.q[ d->recordQ.in ]));
					while ( (0x00 == (inb(d->baseAddress+4) & 0x80)) && dataRecordSize < 512 )
					{
//						printk(KERN_INFO "DR read flag[%X]\n", inb(d->baseAddress+4));
						d->recordQ.q[ d->recordQ.in ][dataRecordSize++] = inb(d->baseAddress+0xC);
					}
					printk("PLX data record size = %i\n", dataRecordSize);
				}
            d->recordQ.in = (d->recordQ.in + 1) % SIZE;   //increment in (write) pointer
            wake_up_interruptible(&(d->recordWaitQ)); //wake up ioctl
         } //else FULL 
         break;

      default: //EI (0xCx, Dx, Ex)  and UI (0xf0 to ff) //CACHE the status byte for later retreival the next time ioctl is called from user mode                   
         if( d->interruptQ.out != (d->interruptQ.in + 1) % SIZE ) //circular buffer NOT FULL (will lose new status bytes if full--old ones are retained)
         {
            d->interruptQ.q[ d->interruptQ.in ] = statusByte;   //store status byte read above
            d->interruptQ.in = (d->interruptQ.in + 1) % SIZE;   //increment in (write) pointer
            wake_up_interruptible(&(d->interruptWaitQ)); //wake up ioctl
         } //else FULL 
                                       
         break;
   }//switch

   return IRQ_HANDLED;
}
Beispiel #15
0
Datei: pic.c Projekt: drewt/Telos
//-----------------------------------------------------------------------------
void pic_eoi(void)
{
	outb(PIC1_CMD, PIC_EOI);
	outb(PIC2_CMD, PIC_EOI);
}
Beispiel #16
0
static long sp5100_tco_ioctl(struct file *file, unsigned int cmd,
			     unsigned long arg)
{
	int new_options, retval = -EINVAL;
	int new_heartbeat;
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options =		WDIOF_SETTIMEOUT |
					WDIOF_KEEPALIVEPING |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		TCO_MODULE_NAME,
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident,
			sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_SETOPTIONS:
		if (get_user(new_options, p))
			return -EFAULT;
		if (new_options & WDIOS_DISABLECARD) {
			tco_timer_stop();
			retval = 0;
		}
		if (new_options & WDIOS_ENABLECARD) {
			tco_timer_start();
			tco_timer_keepalive();
			retval = 0;
		}
		return retval;
	case WDIOC_KEEPALIVE:
		tco_timer_keepalive();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_heartbeat, p))
			return -EFAULT;
		if (tco_timer_set_heartbeat(new_heartbeat))
			return -EINVAL;
		tco_timer_keepalive();
		/* Fall through */
	case WDIOC_GETTIMEOUT:
		return put_user(heartbeat, p);
	default:
		return -ENOTTY;
	}
}

/*
 * Kernel Interfaces
 */

static const struct file_operations sp5100_tco_fops = {
	.owner =		THIS_MODULE,
	.llseek =		no_llseek,
	.write =		sp5100_tco_write,
	.unlocked_ioctl =	sp5100_tco_ioctl,
	.open =			sp5100_tco_open,
	.release =		sp5100_tco_release,
};

static struct miscdevice sp5100_tco_miscdev = {
	.minor =	WATCHDOG_MINOR,
	.name =		"watchdog",
	.fops =		&sp5100_tco_fops,
};

/*
 * Data for PCI driver interface
 *
 * This data only exists for exporting the supported
 * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
 * register a pci_driver, because someone else might
 * want to register another driver on the same PCI id.
 */
static DEFINE_PCI_DEVICE_TABLE(sp5100_tco_pci_tbl) = {
	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
	  PCI_ANY_ID, },
	{ 0, },			/* End of list */
};
MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);

/*
 * Init & exit routines
 */

static unsigned char __devinit sp5100_tco_setupdevice(void)
{
	struct pci_dev *dev = NULL;
	u32 val;

	/* Match the PCI device */
	for_each_pci_dev(dev) {
		if (pci_match_id(sp5100_tco_pci_tbl, dev) != NULL) {
			sp5100_tco_pci = dev;
			break;
		}
	}

	if (!sp5100_tco_pci)
		return 0;

	/* Request the IO ports used by this driver */
	pm_iobase = SP5100_IO_PM_INDEX_REG;
	if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) {
		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
			pm_iobase);
		goto exit;
	}

	/* Find the watchdog base address. */
	outb(SP5100_PM_WATCHDOG_BASE3, SP5100_IO_PM_INDEX_REG);
	val = inb(SP5100_IO_PM_DATA_REG);
	outb(SP5100_PM_WATCHDOG_BASE2, SP5100_IO_PM_INDEX_REG);
	val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
	outb(SP5100_PM_WATCHDOG_BASE1, SP5100_IO_PM_INDEX_REG);
	val = val << 8 | inb(SP5100_IO_PM_DATA_REG);
	outb(SP5100_PM_WATCHDOG_BASE0, SP5100_IO_PM_INDEX_REG);
	/* Low three bits of BASE0 are reserved. */
	val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);

	if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
								"SP5100 TCO")) {
		printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
			val);
		goto unreg_region;
	}
	tcobase_phys = val;

	tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
	if (tcobase == 0) {
		printk(KERN_ERR PFX "failed to get tcobase address\n");
		goto unreg_mem_region;
	}

	/* Enable watchdog decode bit */
	pci_read_config_dword(sp5100_tco_pci,
			      SP5100_PCI_WATCHDOG_MISC_REG,
			      &val);

	val |= SP5100_PCI_WATCHDOG_DECODE_EN;

	pci_write_config_dword(sp5100_tco_pci,
			       SP5100_PCI_WATCHDOG_MISC_REG,
			       val);

	/* Enable Watchdog timer and set the resolution to 1 sec. */
	outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
	val = inb(SP5100_IO_PM_DATA_REG);
	val |= SP5100_PM_WATCHDOG_SECOND_RES;
	val &= ~SP5100_PM_WATCHDOG_DISABLE;
	outb(val, SP5100_IO_PM_DATA_REG);

	/* Check that the watchdog action is set to reset the system. */
	val = readl(SP5100_WDT_CONTROL(tcobase));
	val &= ~SP5100_PM_WATCHDOG_ACTION_RESET;
	writel(val, SP5100_WDT_CONTROL(tcobase));

	/* Set a reasonable heartbeat before we stop the timer */
	tco_timer_set_heartbeat(heartbeat);

	/*
	 * Stop the TCO before we change anything so we don't race with
	 * a zeroed timer.
	 */
	tco_timer_stop();

	/* Done */
	return 1;

unreg_mem_region:
	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
unreg_region:
	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
exit:
	return 0;
}

static int __devinit sp5100_tco_init(struct platform_device *dev)
{
	int ret;
	u32 val;

	/* Check whether or not the hardware watchdog is there. If found, then
	 * set it up.
	 */
	if (!sp5100_tco_setupdevice())
		return -ENODEV;

	/* Check to see if last reboot was due to watchdog timeout */
	printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n",
	       readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ?
		      "" : "not ");

	/* Clear out the old status */
	val = readl(SP5100_WDT_CONTROL(tcobase));
	val &= ~SP5100_PM_WATCHDOG_FIRED;
	writel(val, SP5100_WDT_CONTROL(tcobase));

	/*
	 * Check that the heartbeat value is within it's range.
	 * If not, reset to the default.
	 */
	if (tco_timer_set_heartbeat(heartbeat)) {
		heartbeat = WATCHDOG_HEARTBEAT;
		tco_timer_set_heartbeat(heartbeat);
	}

	ret = misc_register(&sp5100_tco_miscdev);
	if (ret != 0) {
		printk(KERN_ERR PFX "cannot register miscdev on minor="
		       "%d (err=%d)\n",
		       WATCHDOG_MINOR, ret);
		goto exit;
	}

	clear_bit(0, &timer_alive);

	printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec"
		" (nowayout=%d)\n",
		tcobase, heartbeat, nowayout);

	return 0;

exit:
	iounmap(tcobase);
	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
	return ret;
}

static void __devexit sp5100_tco_cleanup(void)
{
	/* Stop the timer before we leave */
	if (!nowayout)
		tco_timer_stop();

	/* Deregister */
	misc_deregister(&sp5100_tco_miscdev);
	iounmap(tcobase);
	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
}

static int __devexit sp5100_tco_remove(struct platform_device *dev)
{
	if (tcobase)
		sp5100_tco_cleanup();
	return 0;
}

static void sp5100_tco_shutdown(struct platform_device *dev)
{
	tco_timer_stop();
}

static struct platform_driver sp5100_tco_driver = {
	.probe		= sp5100_tco_init,
	.remove		= __devexit_p(sp5100_tco_remove),
	.shutdown	= sp5100_tco_shutdown,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= TCO_MODULE_NAME,
	},
};

static int __init sp5100_tco_init_module(void)
{
	int err;

	printk(KERN_INFO PFX "SP5100 TCO WatchDog Timer Driver v%s\n",
	       TCO_VERSION);

	err = platform_driver_register(&sp5100_tco_driver);
	if (err)
		return err;

	sp5100_tco_platform_device = platform_device_register_simple(
					TCO_MODULE_NAME, -1, NULL, 0);
	if (IS_ERR(sp5100_tco_platform_device)) {
		err = PTR_ERR(sp5100_tco_platform_device);
		goto unreg_platform_driver;
	}

	return 0;

unreg_platform_driver:
	platform_driver_unregister(&sp5100_tco_driver);
	return err;
}
Beispiel #17
0
/*===========================================================================*
 *				intr_init				     *
 *===========================================================================*/
PUBLIC int intr_init(const int mine, const int auto_eoi)
{
/* Initialize the 8259s, finishing with all interrupts disabled.  This is
 * only done in protected mode, in real mode we don't touch the 8259s, but
 * use the BIOS locations instead.  The flag "mine" is set if the 8259s are
 * to be programmed for MINIX, or to be reset to what the BIOS expects.
 */

      /* The AT and newer PS/2 have two interrupt controllers, one master,
       * one slaved at IRQ 2.  (We don't have to deal with the PC that
       * has just one controller, because it must run in real mode.)
       */
      outb( INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
      outb( INT_CTLMASK, mine == INTS_MINIX ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
					/* ICW2 for master */
      outb( INT_CTLMASK, (1 << CASCADE_IRQ));
					/* ICW3 tells slaves */
      if (auto_eoi)
          outb( INT_CTLMASK, ICW4_AT_AEOI_MASTER);
      else
          outb( INT_CTLMASK, ICW4_AT_MASTER);
      outb( INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
      outb( INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
      outb( INT2_CTLMASK, mine == INTS_MINIX ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
						/* ICW2 for slave */
      outb( INT2_CTLMASK, CASCADE_IRQ);	/* ICW3 is slave nr */
      if (auto_eoi)
         outb( INT2_CTLMASK, ICW4_AT_AEOI_SLAVE);
      else
         outb( INT2_CTLMASK, ICW4_AT_SLAVE);
      outb( INT2_CTLMASK, ~0);		/* IRQ 8-15 mask */

      /* Copy the BIOS vectors from the BIOS to the Minix location, so we
       * can still make BIOS calls without reprogramming the i8259s.
       */
#if IRQ0_VECTOR != BIOS_IRQ0_VEC
      phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
#endif
#if IRQ8_VECTOR != BIOS_IRQ8_VEC
      phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L);
#endif

  return OK;
}
Beispiel #18
0
static inline void xoutb(unsigned char val, unsigned short port)
{
	pr_debug("outb(val=%.2x,port=%.4x)\n", val, port);
	outb(val, port);
}
Beispiel #19
0
/* Disable 8259 - write 0xFF in OCW1 master and slave. */
PUBLIC void i8259_disable(void)
{
	outb(INT2_CTLMASK, 0xFF);
	outb(INT_CTLMASK, 0xFF);
	inb(INT_CTLMASK);
}
Beispiel #20
0
static void fdc_init_dma_read()
{
    outb(0x0a, 0x06);
    outb(0x0b, 0x56);
    outb(0x0a, 0x02);
}
Beispiel #21
0
Datei: cga.c Projekt: CoryXie/NxM
static void
cgaregw(int index, int data)
{
	outb(0x3D4, index);
	outb(0x3D4+1, data);
}
Beispiel #22
0
static void fdc_init_dma_write()
{
    outb(0x0a, 0x06);
    outb(0x0b, 0x5a);
    outb(0x0a, 0x02);
}
Beispiel #23
0
static void tcic_setb(u_char reg, u_char data)
{
    printk(KERN_DEBUG "tcic_setb(%#lx, %#x)\n", tcic_base+reg, data);
    outb(data, tcic_base+reg);
}
Beispiel #24
0
static void fdc_start_motor0()
{
    outb(FDC_DOR, FDC_DOR_MASK_DRIVE0_MOTOR | FDC_DOR_MASK_RESET);
}
Beispiel #25
0
static inline void
Write_hfc8(hfc4s8s_hw *a, u_char b, u_char c)
{
	SetRegAddr(a, b);
	outb(c, a->iobase);
}
Beispiel #26
0
static void fdc_stop_motor0()
{
    outb(FDC_DOR, FDC_DOR_MASK_RESET);
}
Beispiel #27
0
void
smm_init()
{
    if (CONFIG_COREBOOT)
        // SMM only supported on emulators.
        return;
    if (!CONFIG_USE_SMM)
        return;

    dprintf(3, "init smm\n");

    // This code is hardcoded for PIIX4 Power Management device.
    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL
                              , PCI_DEVICE_ID_INTEL_82371AB_3);
    if (bdf < 0)
        // Device not found
        return;
    int i440_bdf = pci_find_device(PCI_VENDOR_ID_INTEL
                                   , PCI_DEVICE_ID_INTEL_82441);
    if (i440_bdf < 0)
        return;

    /* check if SMM init is already done */
    u32 value = pci_config_readl(bdf, 0x58);
    if (value & (1 << 25))
        return;

    /* enable the SMM memory window */
    pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x48);

    /* save original memory content */
    memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE);

    /* copy the SMM relocation code */
    memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start,
           &smm_relocation_end - &smm_relocation_start);

    /* enable SMI generation when writing to the APMC register */
    pci_config_writel(bdf, 0x58, value | (1 << 25));

    /* init APM status port */
    outb(0x01, PORT_SMI_STATUS);

    /* raise an SMI interrupt */
    outb(0x00, PORT_SMI_CMD);

    /* wait until SMM code executed */
    while (inb(PORT_SMI_STATUS) != 0x00)
        ;

    /* restore original memory content */
    memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE);

    /* copy the SMM code */
    memcpy((void *)BUILD_SMM_ADDR, &smm_code_start
           , &smm_code_end - &smm_code_start);
    wbinvd();

    /* close the SMM memory window and enable normal SMM */
    pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x08);
}
Beispiel #28
0
Datei: pic.c Projekt: drewt/Telos
//-----------------------------------------------------------------------------
void pic_init(u16 off1, u16 off2)
{
	/* master PIC */
	outb(PIC1_CMD, 0x11);
	outb(PIC1_DAT, off1);
	outb(PIC1_DAT, 0x4);
	outb(PIC1_DAT, 0x1);
	outb(PIC1_CMD, 0xB);
	/* slave PIC */
	outb(PIC2_CMD, 0x11);
	outb(PIC2_DAT, off2);
	outb(PIC2_DAT, 0x2);
	outb(PIC2_DAT, 0xB);
	outb(PIC2_CMD, 0xB);
	/* mask all interrupts */
	outb(PIC2_DAT, 0xFF);
	outb(PIC1_DAT, 0xFF);
}
Beispiel #29
0
void	irq_mask_all()
{
	outb(PIC1_DATA, 0xFF);
	outb(PIC2_DATA, 0xFF);
}
Beispiel #30
0
Datei: ps2.c Projekt: PyroOS/Pyro
status_t ps2_ioctl( void* pNode, void* pCookie, uint32 nCommand, void* pArgs, bool bFromKernel )
{
	PS2_Port_s* psPort = (PS2_Port_s*)pNode;
	uint32 nFlg;
	
	if( psPort->bIsAux )
		return( 0 );
		
	
		
	switch( nCommand )
	{
		case IOCTL_KBD_LEDRST:
			g_nKbdLedStatus=0;
			break;

		case IOCTL_KBD_SCRLOC:
			g_nKbdLedStatus ^= 0x01;
			break;

		case IOCTL_KBD_NUMLOC:
			g_nKbdLedStatus ^= 0x02;
			break;

		case IOCTL_KBD_CAPLOC:
			g_nKbdLedStatus ^= 0x04;
			break;

		default:
			printk( "PS2: Unknown IOCTL %x\n",(int)nCommand );
			break;
	}
	
	/* Write command */
	psPort->nAckReceived = 0;
	nFlg = spinlock_disable( &g_sLock );
	ps2_wait_write();
	outb( PS2_CMD_KBD_SETLEDS, PS2_DATA_REG );
	spinunlock_enable( &g_sLock, nFlg );
	int i = 0;
	while( psPort->nAckReceived == 0 && i < 200 )
	{
		snooze( 1000 );
		i++;
	}
	if( psPort->nAckReceived == -1 ) {
		printk( "Could not set LED status: Hardware reported an error for the command!\n" );
		return( 0 );
	}
	if( i == 200 ) {
		printk( "Could not set LED status: Timeout!\n" );
		return( 0 );
	}
	psPort->nAckReceived = 0;
	nFlg = spinlock_disable( &g_sLock );
	ps2_wait_write();
	outb( g_nKbdLedStatus, PS2_DATA_REG );
	spinunlock_enable( &g_sLock, nFlg );
	i = 0;
	while( psPort->nAckReceived == 0 && i < 200 )
	{
		snooze( 1000 );
		i++;
	}
	if( psPort->nAckReceived == -1 ) {
		printk( "Could not set LED status: Hardware reported an error for the data!\n" );
		return( 0 );
	}
	if( i == 200 ) {
		printk( "Could not set LED status: Timeout!\n" );
		return( 0 );
	}
    return( 0 );
}