Commit d06e7a56 authored by Linus Torvalds's avatar Linus Torvalds
parents 346fced8 864ae180
......@@ -444,6 +444,24 @@ config PRINTER
If you have more than 8 printers, you need to increase the LP_NO
macro in lp.c and the PARPORT_MAX macro in parport.h.
config PPDEV
tristate "Support for user-space parallel port device drivers"
depends on PARPORT
---help---
Saying Y to this adds support for /dev/parport device nodes. This
is needed for programs that want portable access to the parallel
port, for instance deviceid (which displays Plug-and-Play device
IDs).
This is the parallel port equivalent of SCSI generic support (sg).
It is safe to say N to this -- it is not needed for normal printing
or parallel port CD-ROM/disk support.
To compile this driver as a module, choose M here: the
module will be called ppdev.
If unsure, say N.
config ENVCTRL
tristate "SUNW, envctrl support"
depends on PCI
......
......@@ -553,13 +553,11 @@ do_ivec:
sllx %g3, 5, %g3
or %g2, %lo(ivector_table), %g2
add %g2, %g3, %g3
ldx [%g3 + 0x08], %g2 /* irq_info */
ldub [%g3 + 0x04], %g4 /* pil */
brz,pn %g2, do_ivec_spurious
mov 1, %g2
mov 1, %g2
sllx %g2, %g4, %g2
sllx %g4, 2, %g4
lduw [%g6 + %g4], %g5 /* g5 = irq_work(cpu, pil) */
stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */
stw %g3, [%g6 + %g4] /* irq_work(cpu, pil) = bucket */
......@@ -567,9 +565,9 @@ do_ivec:
retry
do_ivec_xcall:
mov 0x50, %g1
ldxa [%g1 + %g0] ASI_INTR_R, %g1
srl %g3, 0, %g3
mov 0x60, %g7
ldxa [%g7 + %g0] ASI_INTR_R, %g7
stxa %g0, [%g0] ASI_INTR_RECEIVE
......@@ -581,19 +579,6 @@ do_ivec_xcall:
1: jmpl %g3, %g0
nop
do_ivec_spurious:
stw %g3, [%g6 + 0x00] /* irq_work(cpu, 0) = bucket */
rdpr %pstate, %g5
wrpr %g5, PSTATE_IG | PSTATE_AG, %pstate
sethi %hi(109f), %g7
ba,pt %xcc, etrap
109: or %g7, %lo(109b), %g7
call catch_disabled_ivec
add %sp, PTREGS_OFF, %o0
ba,pt %xcc, rtrap
clr %l6
.globl save_alternate_globals
save_alternate_globals: /* %o0 = save_area */
rdpr %pstate, %o5
......
This diff is collapsed.
......@@ -1303,8 +1303,7 @@ static void psycho_controller_hwinit(struct pci_controller_info *p)
{
u64 tmp;
/* PROM sets the IRQ retry value too low, increase it. */
psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 0xff);
psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 5);
/* Enable arbiter for all PCI slots. */
tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL);
......
......@@ -595,6 +595,23 @@ static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
return ret;
}
/* When a device lives behind a bridge deeper in the PCI bus topology
* than APB, a special sequence must run to make sure all pending DMA
* transfers at the time of IRQ delivery are visible in the coherency
* domain by the cpu. This sequence is to perform a read on the far
* side of the non-APB bridge, then perform a read of Sabre's DMA
* write-sync register.
*/
static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
{
struct pci_dev *pdev = _arg1;
unsigned long sync_reg = (unsigned long) _arg2;
u16 _unused;
pci_read_config_word(pdev, PCI_VENDOR_ID, &_unused);
sabre_read(sync_reg);
}
static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev,
unsigned int ino)
......@@ -639,24 +656,14 @@ static unsigned int __init sabre_irq_build(struct pci_pbm_info *pbm,
if (pdev) {
struct pcidev_cookie *pcp = pdev->sysdata;
/* When a device lives behind a bridge deeper in the
* PCI bus topology than APB, a special sequence must
* run to make sure all pending DMA transfers at the
* time of IRQ delivery are visible in the coherency
* domain by the cpu. This sequence is to perform
* a read on the far side of the non-APB bridge, then
* perform a read of Sabre's DMA write-sync register.
*
* Currently, the PCI_CONFIG register for the device
* is used for this read from the far side of the bridge.
*/
if (pdev->bus->number != pcp->pbm->pci_first_busno) {
bucket->flags |= IBF_DMA_SYNC;
bucket->synctab_ent = dma_sync_reg_table_entry++;
dma_sync_reg_table[bucket->synctab_ent] =
(unsigned long) sabre_pci_config_mkaddr(
pcp->pbm,
pdev->bus->number, pdev->devfn, PCI_COMMAND);
struct pci_controller_info *p = pcp->pbm->parent;
struct irq_desc *d = bucket->irq_info;
d->pre_handler = sabre_wsync_handler;
d->pre_handler_arg1 = pdev;
d->pre_handler_arg2 = (void *)
p->pbm_A.controller_regs + SABRE_WRSYNC;
}
}
return __irq(bucket);
......@@ -1626,10 +1633,9 @@ void __init sabre_init(int pnode, char *model_name)
*/
p->pbm_A.controller_regs = pr_regs[0].phys_addr;
p->pbm_B.controller_regs = pr_regs[0].phys_addr;
pci_dma_wsync = p->pbm_A.controller_regs + SABRE_WRSYNC;
printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n",
p->pbm_A.controller_regs, pci_dma_wsync);
printk("PCI: Found SABRE, main regs at %016lx\n",
p->pbm_A.controller_regs);
/* Clear interrupts */
......
......@@ -15,6 +15,7 @@
#include <asm/iommu.h>
#include <asm/irq.h>
#include <asm/upa.h>
#include <asm/pstate.h>
#include "pci_impl.h"
#include "iommu_common.h"
......@@ -326,6 +327,44 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
return ret;
}
static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
{
unsigned long sync_reg = (unsigned long) _arg2;
u64 mask = 1 << (__irq_ino(__irq(bucket)) & IMAP_INO);
u64 val;
int limit;
schizo_write(sync_reg, mask);
limit = 100000;
val = 0;
while (--limit) {
val = schizo_read(sync_reg);
if (!(val & mask))
break;
}
if (limit <= 0) {
printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n",
val, mask);
}
if (_arg1) {
static unsigned char cacheline[64]
__attribute__ ((aligned (64)));
__asm__ __volatile__("rd %%fprs, %0\n\t"
"or %0, %4, %1\n\t"
"wr %1, 0x0, %%fprs\n\t"
"stda %%f0, [%5] %6\n\t"
"wr %0, 0x0, %%fprs\n\t"
"membar #Sync"
: "=&r" (mask), "=&r" (val)
: "0" (mask), "1" (val),
"i" (FPRS_FEF), "r" (&cacheline[0]),
"i" (ASI_BLK_COMMIT_P));
}
}
static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev,
unsigned int ino)
......@@ -369,6 +408,15 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));
bucket->flags |= IBF_PCI;
if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
struct irq_desc *p = bucket->irq_info;
p->pre_handler = tomatillo_wsync_handler;
p->pre_handler_arg1 = ((pbm->chip_version <= 4) ?
(void *) 1 : (void *) 0);
p->pre_handler_arg2 = (void *) pbm->sync_reg;
}
return __irq(bucket);
}
......@@ -885,6 +933,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
#define SCHIZO_PCI_CTRL (0x2000UL)
#define SCHIZO_PCICTRL_BUS_UNUS (1UL << 63UL) /* Safari */
#define SCHIZO_PCICTRL_DTO_INT (1UL << 61UL) /* Tomatillo */
#define SCHIZO_PCICTRL_ARB_PRIO (0x1ff << 52UL) /* Tomatillo */
#define SCHIZO_PCICTRL_ESLCK (1UL << 51UL) /* Safari */
#define SCHIZO_PCICTRL_ERRSLOT (7UL << 48UL) /* Safari */
......@@ -1887,37 +1936,27 @@ static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
{
u64 tmp;
/* Set IRQ retry to infinity. */
schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY,
SCHIZO_IRQ_RETRY_INF);
schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5);
/* Enable arbiter for all PCI slots. Also, disable PCI interval
* timer so that DTO (Discard TimeOuts) are not reported because
* some Schizo revisions report them erroneously.
*/
tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
if (pbm->chip_type == PBM_CHIP_TYPE_SCHIZO_PLUS &&
pbm->chip_version == 0x5 &&
pbm->chip_revision == 0x1)
tmp |= 0x0f;
else
tmp |= 0xff;
tmp &= ~SCHIZO_PCICTRL_PTO;
/* Enable arbiter for all PCI slots. */
tmp |= 0xff;
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
pbm->chip_version >= 0x2)
tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
else
tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;
if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
tmp |= SCHIZO_PCICTRL_PARK;
else
tmp &= ~SCHIZO_PCICTRL_PARK;
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
pbm->chip_version <= 0x1)
tmp |= (1UL << 61);
tmp |= SCHIZO_PCICTRL_DTO_INT;
else
tmp &= ~(1UL << 61);
tmp &= ~SCHIZO_PCICTRL_DTO_INT;
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
tmp |= (SCHIZO_PCICTRL_MRM_PREF |
......@@ -2015,6 +2054,9 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
pbm->pbm_regs = pr_regs[0].phys_addr;
pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL;
if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL;
sprintf(pbm->name,
(chip_type == PBM_CHIP_TYPE_TOMATILLO ?
"TOMATILLO%d PBM%c" :
......
......@@ -973,7 +973,7 @@ static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_reg
int err;
/* Register IRQ handler. */
err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, SA_STATIC_ALLOC,
err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, 0,
"timer", NULL);
if (err) {
......
......@@ -79,10 +79,6 @@ struct inst {
unsigned char run_length;
unsigned char repeat_byte;
/* These members manage timeouts for programmed delays */
wait_queue_head_t wait_queue;
struct timer_list timer_list;
};
static struct inst instances[BPP_NO];
......@@ -297,16 +293,10 @@ static unsigned short get_pins(unsigned minor)
#endif /* __sparc__ */
static void bpp_wake_up(unsigned long val)
{ wake_up(&instances[val].wait_queue); }
static void snooze(unsigned long snooze_time, unsigned minor)
{
init_timer(&instances[minor].timer_list);
instances[minor].timer_list.expires = jiffies + snooze_time + 1;
instances[minor].timer_list.data = minor;
add_timer(&instances[minor].timer_list);
sleep_on (&instances[minor].wait_queue);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(snooze_time + 1);
}
static int wait_for(unsigned short set, unsigned short clr,
......@@ -880,11 +870,8 @@ static void probeLptPort(unsigned idx)
instances[idx].enhanced = 0;
instances[idx].direction = 0;
instances[idx].mode = COMPATIBILITY;
instances[idx].wait_queue = 0;
instances[idx].run_length = 0;
instances[idx].run_flag = 0;
init_timer(&instances[idx].timer_list);
instances[idx].timer_list.function = bpp_wake_up;
if (!request_region(lpAddr,3, dev_name)) return;
/*
......@@ -977,11 +964,8 @@ static void probeLptPort(unsigned idx)
instances[idx].enhanced = 0;
instances[idx].direction = 0;
instances[idx].mode = COMPATIBILITY;
init_waitqueue_head(&instances[idx].wait_queue);
instances[idx].run_length = 0;
instances[idx].run_flag = 0;
init_timer(&instances[idx].timer_list);
instances[idx].timer_list.function = bpp_wake_up;
if (!rp) return;
......
......@@ -16,6 +16,18 @@
#include <asm/pil.h>
#include <asm/ptrace.h>
struct ino_bucket;
#define MAX_IRQ_DESC_ACTION 4
struct irq_desc {
void (*pre_handler)(struct ino_bucket *, void *, void *);
void *pre_handler_arg1;
void *pre_handler_arg2;
u32 action_active_mask;
struct irqaction action[MAX_IRQ_DESC_ACTION];
};
/* You should not mess with this directly. That's the job of irq.c.
*
* If you make changes here, please update hand coded assembler of
......@@ -42,24 +54,11 @@ struct ino_bucket {
/* Miscellaneous flags. */
/*0x06*/unsigned char flags;
/* This is used to deal with IBF_DMA_SYNC on
* Sabre systems.
*/
/*0x07*/unsigned char synctab_ent;
/* Reference to handler for this IRQ. If this is
* non-NULL this means it is active and should be
* serviced. Else the pending member is set to one
* and later registry of the interrupt checks for
* this condition.
*
* Normally this is just an irq_action structure.
* But, on PCI, if multiple interrupt sources behind
* a bridge have multiple interrupt sources that share
* the same INO bucket, this points to an array of
* pointers to four IRQ action structures.
*/
/*0x08*/void *irq_info;
/* Currently unused. */
/*0x07*/unsigned char __pad;
/* Reference to IRQ descriptor for this bucket. */
/*0x08*/struct irq_desc *irq_info;
/* Sun5 Interrupt Clear Register. */
/*0x10*/unsigned long iclr;
......@@ -69,12 +68,6 @@ struct ino_bucket {
};
#ifdef CONFIG_PCI
extern unsigned long pci_dma_wsync;
extern unsigned long dma_sync_reg_table[256];
extern unsigned char dma_sync_reg_table_entry;
#endif
/* IMAP/ICLR register defines */
#define IMAP_VALID 0x80000000 /* IRQ Enabled */
#define IMAP_TID_UPA 0x7c000000 /* UPA TargetID */
......@@ -90,11 +83,9 @@ extern unsigned char dma_sync_reg_table_entry;
#define ICLR_PENDING 0x00000003 /* Pending state */
/* Only 8-bits are available, be careful. -DaveM */
#define IBF_DMA_SYNC 0x01 /* DMA synchronization behind PCI bridge needed. */
#define IBF_PCI 0x02 /* Indicates PSYCHO/SABRE/SCHIZO PCI interrupt. */
#define IBF_ACTIVE 0x04 /* This interrupt is active and has a handler. */
#define IBF_MULTI 0x08 /* On PCI, indicates shared bucket. */
#define IBF_INPROGRESS 0x10 /* IRQ is being serviced. */
#define IBF_PCI 0x02 /* PSYCHO/SABRE/SCHIZO PCI interrupt. */
#define IBF_ACTIVE 0x04 /* Interrupt is active and has a handler.*/
#define IBF_INPROGRESS 0x10 /* IRQ is being serviced. */
#define NUM_IVECS (IMAP_INR + 1)
extern struct ino_bucket ivector_table[NUM_IVECS];
......
......@@ -145,6 +145,9 @@ struct pci_pbm_info {
/* Physical address base of PBM registers. */
unsigned long pbm_regs;
/* Physical address of DMA sync register, if any. */
unsigned long sync_reg;
/* Opaque 32-bit system bus Port ID. */
u32 portid;
......
......@@ -162,21 +162,6 @@ struct sigstack {
#define MINSIGSTKSZ 4096
#define SIGSTKSZ 16384
#ifdef __KERNEL__
/*
* DJHR
* SA_STATIC_ALLOC is used for the SPARC system to indicate that this
* interrupt handler's irq structure should be statically allocated
* by the request_irq routine.
* The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
* of interrupt usage and that sucks. Also without a flag like this
* it may be possible for the free_irq routine to attempt to free
* statically allocated data.. which is NOT GOOD.
*
*/
#define SA_STATIC_ALLOC 0x80
#endif
#include <asm-generic/signal.h>
struct __new_sigaction {
......
......@@ -346,10 +346,27 @@ COMPATIBLE_IOCTL(PPPOEIOCDFWD)
/* LP */
COMPATIBLE_IOCTL(LPGETSTATUS)
/* ppdev */
COMPATIBLE_IOCTL(PPSETMODE)
COMPATIBLE_IOCTL(PPRSTATUS)
COMPATIBLE_IOCTL(PPRCONTROL)
COMPATIBLE_IOCTL(PPWCONTROL)
COMPATIBLE_IOCTL(PPFCONTROL)
COMPATIBLE_IOCTL(PPRDATA)
COMPATIBLE_IOCTL(PPWDATA)
COMPATIBLE_IOCTL(PPCLAIM)
COMPATIBLE_IOCTL(PPRELEASE)
COMPATIBLE_IOCTL(PPEXCL)
COMPATIBLE_IOCTL(PPYIELD)
COMPATIBLE_IOCTL(PPEXCL)
COMPATIBLE_IOCTL(PPDATADIR)
COMPATIBLE_IOCTL(PPNEGOT)
COMPATIBLE_IOCTL(PPWCTLONIRQ)
COMPATIBLE_IOCTL(PPCLRIRQ)
COMPATIBLE_IOCTL(PPSETPHASE)
COMPATIBLE_IOCTL(PPGETMODES)
COMPATIBLE_IOCTL(PPGETMODE)
COMPATIBLE_IOCTL(PPGETPHASE)
COMPATIBLE_IOCTL(PPGETFLAGS)
COMPATIBLE_IOCTL(PPSETFLAGS)
/* CDROM stuff */
COMPATIBLE_IOCTL(CDROMPAUSE)
COMPATIBLE_IOCTL(CDROMRESUME)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment