Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/ata/pata_isapnp.c
15111 views
1
2
/*
3
* pata-isapnp.c - ISA PnP PATA controller driver.
4
* Copyright 2005/2006 Red Hat Inc, all rights reserved.
5
*
6
* Based in part on ide-pnp.c by Andrey Panin <[email protected]>
7
*/
8
9
#include <linux/kernel.h>
10
#include <linux/module.h>
11
#include <linux/isapnp.h>
12
#include <linux/init.h>
13
#include <linux/blkdev.h>
14
#include <linux/delay.h>
15
#include <scsi/scsi_host.h>
16
#include <linux/ata.h>
17
#include <linux/libata.h>
18
19
#define DRV_NAME "pata_isapnp"
20
#define DRV_VERSION "0.2.5"
21
22
static struct scsi_host_template isapnp_sht = {
23
ATA_PIO_SHT(DRV_NAME),
24
};
25
26
static struct ata_port_operations isapnp_port_ops = {
27
.inherits = &ata_sff_port_ops,
28
.cable_detect = ata_cable_40wire,
29
};
30
31
static struct ata_port_operations isapnp_noalt_port_ops = {
32
.inherits = &ata_sff_port_ops,
33
.cable_detect = ata_cable_40wire,
34
/* No altstatus so we don't want to use the lost interrupt poll */
35
.lost_interrupt = ATA_OP_NULL,
36
};
37
38
/**
39
* isapnp_init_one - attach an isapnp interface
40
* @idev: PnP device
41
* @dev_id: matching detect line
42
*
43
* Register an ISA bus IDE interface. Such interfaces are PIO 0 and
44
* non shared IRQ.
45
*/
46
47
static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev_id)
48
{
49
struct ata_host *host;
50
struct ata_port *ap;
51
void __iomem *cmd_addr, *ctl_addr;
52
int irq = 0;
53
irq_handler_t handler = NULL;
54
55
if (pnp_port_valid(idev, 0) == 0)
56
return -ENODEV;
57
58
if (pnp_irq_valid(idev, 0)) {
59
irq = pnp_irq(idev, 0);
60
handler = ata_sff_interrupt;
61
}
62
63
/* allocate host */
64
host = ata_host_alloc(&idev->dev, 1);
65
if (!host)
66
return -ENOMEM;
67
68
/* acquire resources and fill host */
69
cmd_addr = devm_ioport_map(&idev->dev, pnp_port_start(idev, 0), 8);
70
if (!cmd_addr)
71
return -ENOMEM;
72
73
ap = host->ports[0];
74
75
ap->ops = &isapnp_noalt_port_ops;
76
ap->pio_mask = ATA_PIO0;
77
ap->flags |= ATA_FLAG_SLAVE_POSS;
78
79
ap->ioaddr.cmd_addr = cmd_addr;
80
81
if (pnp_port_valid(idev, 1) == 0) {
82
ctl_addr = devm_ioport_map(&idev->dev,
83
pnp_port_start(idev, 1), 1);
84
ap->ioaddr.altstatus_addr = ctl_addr;
85
ap->ioaddr.ctl_addr = ctl_addr;
86
ap->ops = &isapnp_port_ops;
87
}
88
89
ata_sff_std_ports(&ap->ioaddr);
90
91
ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
92
(unsigned long long)pnp_port_start(idev, 0),
93
(unsigned long long)pnp_port_start(idev, 1));
94
95
/* activate */
96
return ata_host_activate(host, irq, handler, 0,
97
&isapnp_sht);
98
}
99
100
/**
101
* isapnp_remove_one - unplug an isapnp interface
102
* @idev: PnP device
103
*
104
* Remove a previously configured PnP ATA port. Called only on module
105
* unload events as the core does not currently deal with ISAPnP docking.
106
*/
107
108
static void isapnp_remove_one(struct pnp_dev *idev)
109
{
110
struct device *dev = &idev->dev;
111
struct ata_host *host = dev_get_drvdata(dev);
112
113
ata_host_detach(host);
114
}
115
116
static struct pnp_device_id isapnp_devices[] = {
117
/* Generic ESDI/IDE/ATA compatible hard disk controller */
118
{.id = "PNP0600", .driver_data = 0},
119
{.id = ""}
120
};
121
122
MODULE_DEVICE_TABLE(pnp, isapnp_devices);
123
124
static struct pnp_driver isapnp_driver = {
125
.name = DRV_NAME,
126
.id_table = isapnp_devices,
127
.probe = isapnp_init_one,
128
.remove = isapnp_remove_one,
129
};
130
131
static int __init isapnp_init(void)
132
{
133
return pnp_register_driver(&isapnp_driver);
134
}
135
136
static void __exit isapnp_exit(void)
137
{
138
pnp_unregister_driver(&isapnp_driver);
139
}
140
141
MODULE_AUTHOR("Alan Cox");
142
MODULE_DESCRIPTION("low-level driver for ISA PnP ATA");
143
MODULE_LICENSE("GPL");
144
MODULE_VERSION(DRV_VERSION);
145
146
module_init(isapnp_init);
147
module_exit(isapnp_exit);
148
149