brintos

brintos / linux-shallow public Read only

0
0
Text · 6.2 KiB · 7aaba47 Raw
313 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * (c) 1997-1998  Grant R. Guenther <grant@torque.net>4 *5 * epia.c is a low-level protocol driver for Shuttle Technologies6 * EPIA parallel to IDE adapter chip.  This device is now obsolete7 * and has been replaced with the EPAT chip, which is supported8 * by epat.c, however, some devices based on EPIA are still9 * available.10 */11 12#include <linux/module.h>13#include <linux/init.h>14#include <linux/delay.h>15#include <linux/kernel.h>16#include <linux/types.h>17#include <linux/wait.h>18#include <asm/io.h>19#include "pata_parport.h"20 21/*22 * mode codes:  0  nybble reads on port 1, 8-bit writes23 *		1  5/3 reads on ports 1 & 2, 8-bit writes24 *		2  8-bit reads and writes25 *		3  8-bit EPP mode26 *		4  16-bit EPP27 *		5  32-bit EPP28 */29 30#define j44(a, b)	(((a >> 4) & 0x0f) + (b & 0xf0))31#define j53(a, b)	(((a >> 3) & 0x1f) + ((b << 4) & 0xe0))32 33/*34 * cont =  0   IDE register file35 * cont =  1   IDE control registers36 */37static int cont_map[2] = { 0, 0x80 };38 39static int epia_read_regr(struct pi_adapter *pi, int cont, int regr)40{41	int a, b, r;42 43	regr += cont_map[cont];44 45	switch (pi->mode)  {46	case 0:47		r = regr ^ 0x39;48		w0(r); w2(1); w2(3); w0(r);49		a = r1(); w2(1); b = r1(); w2(4);50		return j44(a, b);51	case 1:52		r = regr ^ 0x31;53		w0(r); w2(1); w0(r & 0x37);54		w2(3); w2(5); w0(r | 0xf0);55		a = r1(); b = r2(); w2(4);56		return j53(a, b);57	case 2:58		r = regr^0x29;59		w0(r); w2(1); w2(0X21); w2(0x23);60		a = r0(); w2(4);61		return a;62	case 3:63	case 4:64	case 5:65		w3(regr); w2(0x24); a = r4(); w2(4);66		return a;67	}68 69	return -1;70}71 72static void epia_write_regr(struct pi_adapter *pi, int cont, int regr, int val)73{74	int  r;75 76	regr += cont_map[cont];77 78	switch (pi->mode)  {79	case 0:80	case 1:81	case 2:82		r = regr ^ 0x19;83		w0(r); w2(1); w0(val); w2(3); w2(4);84		break;85	case 3:86	case 4:87	case 5:88		r = regr ^ 0x40;89		w3(r); w4(val); w2(4);90		break;91	}92}93 94#define WR(r, v)	epia_write_regr(pi, 0, r, v)95#define RR(r)		epia_read_regr(pi, 0, r)96 97/*98 * The use of register 0x84 is entirely unclear - it seems to control99 * some EPP counters ...  currently we know about 3 different block100 * sizes:  the standard 512 byte reads and writes, 12 byte writes and101 * 2048 byte reads (the last two being used in the CDrom drivers.102 */103static void epia_connect(struct pi_adapter *pi)104{105	pi->saved_r0 = r0();106	pi->saved_r2 = r2();107 108	w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);109	w2(1); w2(4);110	if (pi->mode >= 3) {111		w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);112		w2(0x24); w2(0x26); w2(4);113	}114	WR(0x86, 8);115}116 117static void epia_disconnect(struct pi_adapter *pi)118{119	/* WR(0x84,0x10); */120	w0(pi->saved_r0);121	w2(1); w2(4);122	w0(pi->saved_r0);123	w2(pi->saved_r2);124}125 126static void epia_read_block(struct pi_adapter *pi, char *buf, int count)127 128{129	int k, ph, a, b;130 131	switch (pi->mode) {132	case 0:133		w0(0x81); w2(1); w2(3); w0(0xc1);134		ph = 1;135		for (k = 0; k < count; k++) {136			w2(2+ph); a = r1();137			w2(4+ph); b = r1();138			buf[k] = j44(a, b);139			ph = 1 - ph;140		}141		w0(0); w2(4);142		break;143	case 1:144		w0(0x91); w2(1); w0(0x10); w2(3);145		w0(0x51); w2(5); w0(0xd1);146		ph = 1;147		for (k = 0; k < count; k++) {148			w2(4 + ph);149			a = r1(); b = r2();150			buf[k] = j53(a, b);151			ph = 1 - ph;152		}153		w0(0); w2(4);154		break;155	case 2:156		w0(0x89); w2(1); w2(0x23); w2(0x21);157		ph = 1;158		for (k = 0; k < count; k++) {159			w2(0x24 + ph);160			buf[k] = r0();161			ph = 1 - ph;162		}163		w2(6); w2(4);164		break;165	case 3:166		if (count > 512)167			WR(0x84, 3);168		w3(0); w2(0x24);169		for (k = 0; k < count; k++)170			buf[k] = r4();171		w2(4); WR(0x84, 0);172		break;173	case 4:174		if (count > 512)175			WR(0x84, 3);176		w3(0); w2(0x24);177		for (k = 0; k < count / 2; k++)178			((u16 *)buf)[k] = r4w();179		w2(4); WR(0x84, 0);180		break;181	case 5:182		if (count > 512)183			WR(0x84, 3);184		w3(0); w2(0x24);185		for (k = 0; k < count / 4; k++)186			((u32 *)buf)[k] = r4l();187		w2(4); WR(0x84, 0);188		break;189	}190}191 192static void epia_write_block(struct pi_adapter *pi, char *buf, int count)193{194	int ph, k, last, d;195 196	switch (pi->mode) {197	case 0:198	case 1:199	case 2:200		w0(0xa1); w2(1); w2(3); w2(1); w2(5);201		ph = 0;  last = 0x8000;202		for (k = 0; k < count; k++) {203			d = buf[k];204			if (d != last) {205				last = d;206				w0(d);207			}208			w2(4 + ph);209			ph = 1 - ph;210		}211		w2(7); w2(4);212		break;213	case 3:214		if (count < 512)215			WR(0x84, 1);216		w3(0x40);217		for (k = 0; k < count; k++)218			w4(buf[k]);219		if (count < 512)220			WR(0x84, 0);221		break;222	case 4:223		if (count < 512)224			WR(0x84, 1);225		w3(0x40);226		for (k = 0; k < count / 2; k++)227			w4w(((u16 *)buf)[k]);228		if (count < 512)229			WR(0x84, 0);230		break;231	case 5:232		if (count < 512)233			WR(0x84, 1);234		w3(0x40);235		for (k = 0; k < count / 4; k++)236			w4l(((u32 *)buf)[k]);237		if (count < 512)238			WR(0x84, 0);239		break;240	}241}242 243static int epia_test_proto(struct pi_adapter *pi)244{245	int j, k, f;246	int e[2] = { 0, 0 };247	char scratch[512];248 249	epia_connect(pi);250	for (j = 0; j < 2; j++) {251		WR(6, 0xa0 + j * 0x10);252		for (k = 0; k < 256; k++) {253			WR(2, k ^ 0xaa);254			WR(3, k ^ 0x55);255			if (RR(2) != (k ^ 0xaa))256				e[j]++;257		}258		WR(2, 1); WR(3, 1);259	}260	epia_disconnect(pi);261 262	f = 0;263	epia_connect(pi);264	WR(0x84, 8);265	epia_read_block(pi, scratch, 512);266	for (k = 0; k < 256; k++) {267		if ((scratch[2 * k] & 0xff) != ((k + 1) & 0xff))268			f++;269		if ((scratch[2 * k + 1] & 0xff) != ((-2 - k) & 0xff))270			f++;271	}272	WR(0x84, 0);273	epia_disconnect(pi);274 275	dev_dbg(&pi->dev, "epia: port 0x%x, mode %d, test=(%d,%d,%d)\n",276		pi->port, pi->mode, e[0], e[1], f);277 278	return (e[0] && e[1]) || f;279}280 281 282static void epia_log_adapter(struct pi_adapter *pi)283{284	char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32"};285 286	dev_info(&pi->dev,287		 "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n",288		 pi->port, pi->mode, mode[pi->mode], pi->delay);289}290 291static struct pi_protocol epia = {292	.owner		= THIS_MODULE,293	.name		= "epia",294	.max_mode	= 6,295	.epp_first	= 3,296	.default_delay	= 1,297	.max_units	= 1,298	.write_regr	= epia_write_regr,299	.read_regr	= epia_read_regr,300	.write_block	= epia_write_block,301	.read_block	= epia_read_block,302	.connect	= epia_connect,303	.disconnect	= epia_disconnect,304	.test_proto	= epia_test_proto,305	.log_adapter	= epia_log_adapter,306};307 308MODULE_LICENSE("GPL");309MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");310MODULE_DESCRIPTION("Shuttle Technologies EPIA parallel port IDE adapter "311		   "protocol driver");312module_pata_parport_driver(epia);313