cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

daisy.c (13248B)


      1/*
      2 * IEEE 1284.3 Parallel port daisy chain and multiplexor code
      3 * 
      4 * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
      5 *
      6 * This program is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU General Public License
      8 * as published by the Free Software Foundation; either version
      9 * 2 of the License, or (at your option) any later version.
     10 *
     11 * ??-12-1998: Initial implementation.
     12 * 31-01-1999: Make port-cloning transparent.
     13 * 13-02-1999: Move DeviceID technique from parport_probe.
     14 * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
     15 * 22-02-2000: Count devices that are actually detected.
     16 *
     17 * Any part of this program may be used in documents licensed under
     18 * the GNU Free Documentation License, Version 1.1 or any later version
     19 * published by the Free Software Foundation.
     20 */
     21
     22#include <linux/module.h>
     23#include <linux/parport.h>
     24#include <linux/delay.h>
     25#include <linux/slab.h>
     26#include <linux/sched/signal.h>
     27
     28#include <asm/current.h>
     29#include <linux/uaccess.h>
     30
     31#undef DEBUG
     32
     33static struct daisydev {
     34	struct daisydev *next;
     35	struct parport *port;
     36	int daisy;
     37	int devnum;
     38} *topology = NULL;
     39static DEFINE_SPINLOCK(topology_lock);
     40
     41static int numdevs;
     42static bool daisy_init_done;
     43
     44/* Forward-declaration of lower-level functions. */
     45static int mux_present(struct parport *port);
     46static int num_mux_ports(struct parport *port);
     47static int select_port(struct parport *port);
     48static int assign_addrs(struct parport *port);
     49
     50/* Add a device to the discovered topology. */
     51static void add_dev(int devnum, struct parport *port, int daisy)
     52{
     53	struct daisydev *newdev, **p;
     54	newdev = kmalloc(sizeof(struct daisydev), GFP_KERNEL);
     55	if (newdev) {
     56		newdev->port = port;
     57		newdev->daisy = daisy;
     58		newdev->devnum = devnum;
     59		spin_lock(&topology_lock);
     60		for (p = &topology; *p && (*p)->devnum<devnum; p = &(*p)->next)
     61			;
     62		newdev->next = *p;
     63		*p = newdev;
     64		spin_unlock(&topology_lock);
     65	}
     66}
     67
     68/* Clone a parport (actually, make an alias). */
     69static struct parport *clone_parport(struct parport *real, int muxport)
     70{
     71	struct parport *extra = parport_register_port(real->base,
     72						       real->irq,
     73						       real->dma,
     74						       real->ops);
     75	if (extra) {
     76		extra->portnum = real->portnum;
     77		extra->physport = real;
     78		extra->muxport = muxport;
     79		real->slaves[muxport-1] = extra;
     80	}
     81
     82	return extra;
     83}
     84
     85static int daisy_drv_probe(struct pardevice *par_dev)
     86{
     87	struct device_driver *drv = par_dev->dev.driver;
     88
     89	if (strcmp(drv->name, "daisy_drv"))
     90		return -ENODEV;
     91	if (strcmp(par_dev->name, daisy_dev_name))
     92		return -ENODEV;
     93
     94	return 0;
     95}
     96
     97static struct parport_driver daisy_driver = {
     98	.name = "daisy_drv",
     99	.probe = daisy_drv_probe,
    100	.devmodel = true,
    101};
    102
    103/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains.
    104 * Return value is number of devices actually detected. */
    105int parport_daisy_init(struct parport *port)
    106{
    107	int detected = 0;
    108	char *deviceid;
    109	static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
    110	int num_ports;
    111	int i;
    112	int last_try = 0;
    113
    114	if (!daisy_init_done) {
    115		/*
    116		 * flag should be marked true first as
    117		 * parport_register_driver() might try to load the low
    118		 * level driver which will lead to announcing new ports
    119		 * and which will again come back here at
    120		 * parport_daisy_init()
    121		 */
    122		daisy_init_done = true;
    123		i = parport_register_driver(&daisy_driver);
    124		if (i) {
    125			pr_err("daisy registration failed\n");
    126			daisy_init_done = false;
    127			return i;
    128		}
    129	}
    130
    131again:
    132	/* Because this is called before any other devices exist,
    133	 * we don't have to claim exclusive access.  */
    134
    135	/* If mux present on normal port, need to create new
    136	 * parports for each extra port. */
    137	if (port->muxport < 0 && mux_present(port) &&
    138	    /* don't be fooled: a mux must have 2 or 4 ports. */
    139	    ((num_ports = num_mux_ports(port)) == 2 || num_ports == 4)) {
    140		/* Leave original as port zero. */
    141		port->muxport = 0;
    142		pr_info("%s: 1st (default) port of %d-way multiplexor\n",
    143			port->name, num_ports);
    144		for (i = 1; i < num_ports; i++) {
    145			/* Clone the port. */
    146			struct parport *extra = clone_parport(port, i);
    147			if (!extra) {
    148				if (signal_pending(current))
    149					break;
    150
    151				schedule();
    152				continue;
    153			}
    154
    155			pr_info("%s: %d%s port of %d-way multiplexor on %s\n",
    156				extra->name, i + 1, th[i + 1], num_ports,
    157				port->name);
    158
    159			/* Analyse that port too.  We won't recurse
    160			   forever because of the 'port->muxport < 0'
    161			   test above. */
    162			parport_daisy_init(extra);
    163		}
    164	}
    165
    166	if (port->muxport >= 0)
    167		select_port(port);
    168
    169	parport_daisy_deselect_all(port);
    170	detected += assign_addrs(port);
    171
    172	/* Count the potential legacy device at the end. */
    173	add_dev(numdevs++, port, -1);
    174
    175	/* Find out the legacy device's IEEE 1284 device ID. */
    176	deviceid = kmalloc(1024, GFP_KERNEL);
    177	if (deviceid) {
    178		if (parport_device_id(numdevs - 1, deviceid, 1024) > 2)
    179			detected++;
    180
    181		kfree(deviceid);
    182	}
    183
    184	if (!detected && !last_try) {
    185		/* No devices were detected.  Perhaps they are in some
    186                   funny state; let's try to reset them and see if
    187                   they wake up. */
    188		parport_daisy_fini(port);
    189		parport_write_control(port, PARPORT_CONTROL_SELECT);
    190		udelay(50);
    191		parport_write_control(port,
    192				       PARPORT_CONTROL_SELECT |
    193				       PARPORT_CONTROL_INIT);
    194		udelay(50);
    195		last_try = 1;
    196		goto again;
    197	}
    198
    199	return detected;
    200}
    201
    202/* Forget about devices on a physical port. */
    203void parport_daisy_fini(struct parport *port)
    204{
    205	struct daisydev **p;
    206
    207	spin_lock(&topology_lock);
    208	p = &topology;
    209	while (*p) {
    210		struct daisydev *dev = *p;
    211		if (dev->port != port) {
    212			p = &dev->next;
    213			continue;
    214		}
    215		*p = dev->next;
    216		kfree(dev);
    217	}
    218
    219	/* Gaps in the numbering could be handled better.  How should
    220           someone enumerate through all IEEE1284.3 devices in the
    221           topology?. */
    222	if (!topology) numdevs = 0;
    223	spin_unlock(&topology_lock);
    224	return;
    225}
    226
    227/**
    228 *	parport_open - find a device by canonical device number
    229 *	@devnum: canonical device number
    230 *	@name: name to associate with the device
    231 *
    232 *	This function is similar to parport_register_device(), except
    233 *	that it locates a device by its number rather than by the port
    234 *	it is attached to.
    235 *
    236 *	All parameters except for @devnum are the same as for
    237 *	parport_register_device().  The return value is the same as
    238 *	for parport_register_device().
    239 **/
    240
    241struct pardevice *parport_open(int devnum, const char *name)
    242{
    243	struct daisydev *p = topology;
    244	struct pardev_cb par_cb;
    245	struct parport *port;
    246	struct pardevice *dev;
    247	int daisy;
    248
    249	memset(&par_cb, 0, sizeof(par_cb));
    250	spin_lock(&topology_lock);
    251	while (p && p->devnum != devnum)
    252		p = p->next;
    253
    254	if (!p) {
    255		spin_unlock(&topology_lock);
    256		return NULL;
    257	}
    258
    259	daisy = p->daisy;
    260	port = parport_get_port(p->port);
    261	spin_unlock(&topology_lock);
    262
    263	dev = parport_register_dev_model(port, name, &par_cb, devnum);
    264	parport_put_port(port);
    265	if (!dev)
    266		return NULL;
    267
    268	dev->daisy = daisy;
    269
    270	/* Check that there really is a device to select. */
    271	if (daisy >= 0) {
    272		int selected;
    273		parport_claim_or_block(dev);
    274		selected = port->daisy;
    275		parport_release(dev);
    276
    277		if (selected != daisy) {
    278			/* No corresponding device. */
    279			parport_unregister_device(dev);
    280			return NULL;
    281		}
    282	}
    283
    284	return dev;
    285}
    286
    287/**
    288 *	parport_close - close a device opened with parport_open()
    289 *	@dev: device to close
    290 *
    291 *	This is to parport_open() as parport_unregister_device() is to
    292 *	parport_register_device().
    293 **/
    294
    295void parport_close(struct pardevice *dev)
    296{
    297	parport_unregister_device(dev);
    298}
    299
    300/* Send a daisy-chain-style CPP command packet. */
    301static int cpp_daisy(struct parport *port, int cmd)
    302{
    303	unsigned char s;
    304
    305	parport_data_forward(port);
    306	parport_write_data(port, 0xaa); udelay(2);
    307	parport_write_data(port, 0x55); udelay(2);
    308	parport_write_data(port, 0x00); udelay(2);
    309	parport_write_data(port, 0xff); udelay(2);
    310	s = parport_read_status(port) & (PARPORT_STATUS_BUSY
    311					  | PARPORT_STATUS_PAPEROUT
    312					  | PARPORT_STATUS_SELECT
    313					  | PARPORT_STATUS_ERROR);
    314	if (s != (PARPORT_STATUS_BUSY
    315		  | PARPORT_STATUS_PAPEROUT
    316		  | PARPORT_STATUS_SELECT
    317		  | PARPORT_STATUS_ERROR)) {
    318		pr_debug("%s: cpp_daisy: aa5500ff(%02x)\n", port->name, s);
    319		return -ENXIO;
    320	}
    321
    322	parport_write_data(port, 0x87); udelay(2);
    323	s = parport_read_status(port) & (PARPORT_STATUS_BUSY
    324					  | PARPORT_STATUS_PAPEROUT
    325					  | PARPORT_STATUS_SELECT
    326					  | PARPORT_STATUS_ERROR);
    327	if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
    328		pr_debug("%s: cpp_daisy: aa5500ff87(%02x)\n", port->name, s);
    329		return -ENXIO;
    330	}
    331
    332	parport_write_data(port, 0x78); udelay(2);
    333	parport_write_data(port, cmd); udelay(2);
    334	parport_frob_control(port,
    335			      PARPORT_CONTROL_STROBE,
    336			      PARPORT_CONTROL_STROBE);
    337	udelay(1);
    338	s = parport_read_status(port);
    339	parport_frob_control(port, PARPORT_CONTROL_STROBE, 0);
    340	udelay(1);
    341	parport_write_data(port, 0xff); udelay(2);
    342
    343	return s;
    344}
    345
    346/* Send a mux-style CPP command packet. */
    347static int cpp_mux(struct parport *port, int cmd)
    348{
    349	unsigned char s;
    350	int rc;
    351
    352	parport_data_forward(port);
    353	parport_write_data(port, 0xaa); udelay(2);
    354	parport_write_data(port, 0x55); udelay(2);
    355	parport_write_data(port, 0xf0); udelay(2);
    356	parport_write_data(port, 0x0f); udelay(2);
    357	parport_write_data(port, 0x52); udelay(2);
    358	parport_write_data(port, 0xad); udelay(2);
    359	parport_write_data(port, cmd); udelay(2);
    360
    361	s = parport_read_status(port);
    362	if (!(s & PARPORT_STATUS_ACK)) {
    363		pr_debug("%s: cpp_mux: aa55f00f52ad%02x(%02x)\n",
    364			 port->name, cmd, s);
    365		return -EIO;
    366	}
    367
    368	rc = (((s & PARPORT_STATUS_SELECT   ? 1 : 0) << 0) |
    369	      ((s & PARPORT_STATUS_PAPEROUT ? 1 : 0) << 1) |
    370	      ((s & PARPORT_STATUS_BUSY     ? 0 : 1) << 2) |
    371	      ((s & PARPORT_STATUS_ERROR    ? 0 : 1) << 3));
    372
    373	return rc;
    374}
    375
    376void parport_daisy_deselect_all(struct parport *port)
    377{
    378	cpp_daisy(port, 0x30);
    379}
    380
    381int parport_daisy_select(struct parport *port, int daisy, int mode)
    382{
    383	switch (mode)
    384	{
    385		// For these modes we should switch to EPP mode:
    386		case IEEE1284_MODE_EPP:
    387		case IEEE1284_MODE_EPPSL:
    388		case IEEE1284_MODE_EPPSWE:
    389			return !(cpp_daisy(port, 0x20 + daisy) &
    390				 PARPORT_STATUS_ERROR);
    391
    392		// For these modes we should switch to ECP mode:
    393		case IEEE1284_MODE_ECP:
    394		case IEEE1284_MODE_ECPRLE:
    395		case IEEE1284_MODE_ECPSWE: 
    396			return !(cpp_daisy(port, 0xd0 + daisy) &
    397				 PARPORT_STATUS_ERROR);
    398
    399		// Nothing was told for BECP in Daisy chain specification.
    400		// May be it's wise to use ECP?
    401		case IEEE1284_MODE_BECP:
    402		// Others use compat mode
    403		case IEEE1284_MODE_NIBBLE:
    404		case IEEE1284_MODE_BYTE:
    405		case IEEE1284_MODE_COMPAT:
    406		default:
    407			return !(cpp_daisy(port, 0xe0 + daisy) &
    408				 PARPORT_STATUS_ERROR);
    409	}
    410}
    411
    412static int mux_present(struct parport *port)
    413{
    414	return cpp_mux(port, 0x51) == 3;
    415}
    416
    417static int num_mux_ports(struct parport *port)
    418{
    419	return cpp_mux(port, 0x58);
    420}
    421
    422static int select_port(struct parport *port)
    423{
    424	int muxport = port->muxport;
    425	return cpp_mux(port, 0x60 + muxport) == muxport;
    426}
    427
    428static int assign_addrs(struct parport *port)
    429{
    430	unsigned char s;
    431	unsigned char daisy;
    432	int thisdev = numdevs;
    433	int detected;
    434	char *deviceid;
    435
    436	parport_data_forward(port);
    437	parport_write_data(port, 0xaa); udelay(2);
    438	parport_write_data(port, 0x55); udelay(2);
    439	parport_write_data(port, 0x00); udelay(2);
    440	parport_write_data(port, 0xff); udelay(2);
    441	s = parport_read_status(port) & (PARPORT_STATUS_BUSY
    442					  | PARPORT_STATUS_PAPEROUT
    443					  | PARPORT_STATUS_SELECT
    444					  | PARPORT_STATUS_ERROR);
    445	if (s != (PARPORT_STATUS_BUSY
    446		  | PARPORT_STATUS_PAPEROUT
    447		  | PARPORT_STATUS_SELECT
    448		  | PARPORT_STATUS_ERROR)) {
    449		pr_debug("%s: assign_addrs: aa5500ff(%02x)\n", port->name, s);
    450		return 0;
    451	}
    452
    453	parport_write_data(port, 0x87); udelay(2);
    454	s = parport_read_status(port) & (PARPORT_STATUS_BUSY
    455					  | PARPORT_STATUS_PAPEROUT
    456					  | PARPORT_STATUS_SELECT
    457					  | PARPORT_STATUS_ERROR);
    458	if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
    459		pr_debug("%s: assign_addrs: aa5500ff87(%02x)\n", port->name, s);
    460		return 0;
    461	}
    462
    463	parport_write_data(port, 0x78); udelay(2);
    464	s = parport_read_status(port);
    465
    466	for (daisy = 0;
    467	     (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT))
    468		     == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)
    469		     && daisy < 4;
    470	     ++daisy) {
    471		parport_write_data(port, daisy);
    472		udelay(2);
    473		parport_frob_control(port,
    474				      PARPORT_CONTROL_STROBE,
    475				      PARPORT_CONTROL_STROBE);
    476		udelay(1);
    477		parport_frob_control(port, PARPORT_CONTROL_STROBE, 0);
    478		udelay(1);
    479
    480		add_dev(numdevs++, port, daisy);
    481
    482		/* See if this device thought it was the last in the
    483		 * chain. */
    484		if (!(s & PARPORT_STATUS_BUSY))
    485			break;
    486
    487		/* We are seeing pass through status now. We see
    488		   last_dev from next device or if last_dev does not
    489		   work status lines from some non-daisy chain
    490		   device. */
    491		s = parport_read_status(port);
    492	}
    493
    494	parport_write_data(port, 0xff); udelay(2);
    495	detected = numdevs - thisdev;
    496	pr_debug("%s: Found %d daisy-chained devices\n", port->name, detected);
    497
    498	/* Ask the new devices to introduce themselves. */
    499	deviceid = kmalloc(1024, GFP_KERNEL);
    500	if (!deviceid) return 0;
    501
    502	for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
    503		parport_device_id(thisdev, deviceid, 1024);
    504
    505	kfree(deviceid);
    506	return detected;
    507}