1a1917f14Szrj /*-
2a1917f14Szrj * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
3a1917f14Szrj * All rights reserved.
4a1917f14Szrj *
5a1917f14Szrj * Redistribution and use in source and binary forms, with or without
6a1917f14Szrj * modification, are permitted provided that the following conditions
7a1917f14Szrj * are met:
8a1917f14Szrj * 1. Redistributions of source code must retain the above copyright
9a1917f14Szrj * notice, this list of conditions and the following disclaimer,
10a1917f14Szrj * without modification, immediately at the beginning of the file.
11a1917f14Szrj * 2. Redistributions in binary form must reproduce the above copyright
12a1917f14Szrj * notice, this list of conditions and the following disclaimer in the
13a1917f14Szrj * documentation and/or other materials provided with the distribution.
14a1917f14Szrj *
15a1917f14Szrj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16a1917f14Szrj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17a1917f14Szrj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18a1917f14Szrj * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19a1917f14Szrj * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20a1917f14Szrj * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21a1917f14Szrj * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22a1917f14Szrj * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23a1917f14Szrj * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24a1917f14Szrj * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25a1917f14Szrj */
26a1917f14Szrj
27a1917f14Szrj /* local prototypes */
28a1917f14Szrj static int ata_serverworks_chipinit(device_t dev);
29a1917f14Szrj static int ata_serverworks_allocate(device_t dev);
3037c16061Szrj static void ata_serverworks_tf_read(struct ata_request *request);
3137c16061Szrj static void ata_serverworks_tf_write(struct ata_request *request);
32a1917f14Szrj static void ata_serverworks_setmode(device_t dev, int mode);
33a1917f14Szrj
34853eb30dSzrj /* misc defines */
35853eb30dSzrj #define SWKS_33 0
36853eb30dSzrj #define SWKS_66 1
37853eb30dSzrj #define SWKS_100 2
38853eb30dSzrj #define SWKS_MIO 3
39853eb30dSzrj
40a1917f14Szrj /*
41a1917f14Szrj * ServerWorks chipset support functions
42a1917f14Szrj */
43a1917f14Szrj int
ata_serverworks_ident(device_t dev)44a1917f14Szrj ata_serverworks_ident(device_t dev)
45a1917f14Szrj {
46a1917f14Szrj struct ata_pci_controller *ctlr = device_get_softc(dev);
4759503772Szrj static const struct ata_chip_id ids[] =
48853eb30dSzrj {{ ATA_ROSB4, 0x00, SWKS_33, 0, ATA_UDMA2, "ROSB4" },
49853eb30dSzrj { ATA_CSB5, 0x92, SWKS_100, 0, ATA_UDMA5, "CSB5" },
50853eb30dSzrj { ATA_CSB5, 0x00, SWKS_66, 0, ATA_UDMA4, "CSB5" },
51853eb30dSzrj { ATA_CSB6, 0x00, SWKS_100, 0, ATA_UDMA5, "CSB6" },
52853eb30dSzrj { ATA_CSB6_1, 0x00, SWKS_66, 0, ATA_UDMA4, "CSB6" },
53853eb30dSzrj { ATA_HT1000, 0x00, SWKS_100, 0, ATA_UDMA5, "HT1000" },
54878a3234Szrj { ATA_HT1000_S1, 0x00, SWKS_MIO, 4, ATA_SA150, "HT1000" },
55853eb30dSzrj { ATA_HT1000_S2, 0x00, SWKS_MIO, 4, ATA_SA150, "HT1000" },
56853eb30dSzrj { ATA_K2, 0x00, SWKS_MIO, 4, ATA_SA150, "K2" },
57853eb30dSzrj { ATA_FRODO4, 0x00, SWKS_MIO, 4, ATA_SA150, "Frodo4" },
58853eb30dSzrj { ATA_FRODO8, 0x00, SWKS_MIO, 8, ATA_SA150, "Frodo8" },
59a1917f14Szrj { 0, 0, 0, 0, 0, 0}};
60a1917f14Szrj
6159503772Szrj if (pci_get_vendor(dev) != ATA_SERVERWORKS_ID)
62a1917f14Szrj return ENXIO;
63a1917f14Szrj
6459503772Szrj if (!(ctlr->chip = ata_match_chip(dev, ids)))
6559503772Szrj return ENXIO;
6659503772Szrj
6759503772Szrj ata_set_desc(dev);
68a1917f14Szrj ctlr->chipinit = ata_serverworks_chipinit;
69a1917f14Szrj return 0;
70a1917f14Szrj }
71a1917f14Szrj
72a1917f14Szrj static int
ata_serverworks_chipinit(device_t dev)73a1917f14Szrj ata_serverworks_chipinit(device_t dev)
74a1917f14Szrj {
75a1917f14Szrj struct ata_pci_controller *ctlr = device_get_softc(dev);
76a1917f14Szrj
7743156ad7Szrj if (ata_setup_interrupt(dev, ata_generic_intr))
78a1917f14Szrj return ENXIO;
79a1917f14Szrj
80853eb30dSzrj if (ctlr->chip->cfg1 == SWKS_MIO) {
81a1917f14Szrj ctlr->r_type2 = SYS_RES_MEMORY;
82a1917f14Szrj ctlr->r_rid2 = PCIR_BAR(5);
83a1917f14Szrj if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
84a1917f14Szrj &ctlr->r_rid2, RF_ACTIVE))){
85a1917f14Szrj ata_teardown_interrupt(dev);
86a1917f14Szrj return ENXIO;
87a1917f14Szrj }
88a1917f14Szrj
89a1917f14Szrj ctlr->channels = ctlr->chip->cfg2;
90a1917f14Szrj ctlr->allocate = ata_serverworks_allocate;
91a1917f14Szrj ctlr->setmode = ata_sata_setmode;
92a1917f14Szrj return 0;
93a1917f14Szrj }
94853eb30dSzrj else if (ctlr->chip->cfg1 == SWKS_33) {
95a1917f14Szrj device_t *children;
96a1917f14Szrj int nchildren, i;
97a1917f14Szrj
98a1917f14Szrj /* locate the ISA part in the southbridge and enable UDMA33 */
99a1917f14Szrj if (!device_get_children(device_get_parent(dev), &children,&nchildren)){
100a1917f14Szrj for (i = 0; i < nchildren; i++) {
101a1917f14Szrj if (pci_get_devid(children[i]) == ATA_ROSB4_ISA) {
102a1917f14Szrj pci_write_config(children[i], 0x64,
103a1917f14Szrj (pci_read_config(children[i], 0x64, 4) &
104a1917f14Szrj ~0x00002000) | 0x00004000, 4);
105a1917f14Szrj break;
106a1917f14Szrj }
107a1917f14Szrj }
108a1917f14Szrj kfree(children, M_TEMP);
109a1917f14Szrj }
110a1917f14Szrj }
111a1917f14Szrj else {
112a1917f14Szrj pci_write_config(dev, 0x5a,
113a1917f14Szrj (pci_read_config(dev, 0x5a, 1) & ~0x40) |
114*07c11d3bSSascha Wildner ((ctlr->chip->cfg1 == SWKS_100) ? 0x03 : 0x02), 1);
115a1917f14Szrj }
116a1917f14Szrj ctlr->setmode = ata_serverworks_setmode;
117a1917f14Szrj return 0;
118a1917f14Szrj }
119a1917f14Szrj
120a1917f14Szrj static int
ata_serverworks_allocate(device_t dev)121a1917f14Szrj ata_serverworks_allocate(device_t dev)
122a1917f14Szrj {
123a1917f14Szrj struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
124a1917f14Szrj struct ata_channel *ch = device_get_softc(dev);
125a1917f14Szrj int ch_offset;
126a1917f14Szrj int i;
127a1917f14Szrj
128a1917f14Szrj ch_offset = ch->unit * 0x100;
129a1917f14Szrj
130a1917f14Szrj for (i = ATA_DATA; i < ATA_MAX_RES; i++)
131a1917f14Szrj ch->r_io[i].res = ctlr->r_res2;
132a1917f14Szrj
133a1917f14Szrj /* setup ATA registers */
134a1917f14Szrj ch->r_io[ATA_DATA].offset = ch_offset + 0x00;
135a1917f14Szrj ch->r_io[ATA_FEATURE].offset = ch_offset + 0x04;
136a1917f14Szrj ch->r_io[ATA_COUNT].offset = ch_offset + 0x08;
137a1917f14Szrj ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c;
138a1917f14Szrj ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10;
139a1917f14Szrj ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14;
140a1917f14Szrj ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18;
141a1917f14Szrj ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1c;
142a1917f14Szrj ch->r_io[ATA_CONTROL].offset = ch_offset + 0x20;
143a1917f14Szrj ata_default_registers(dev);
144a1917f14Szrj
145a1917f14Szrj /* setup DMA registers */
146a1917f14Szrj ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x30;
147a1917f14Szrj ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x32;
148a1917f14Szrj ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x34;
149a1917f14Szrj
150a1917f14Szrj /* setup SATA registers */
151a1917f14Szrj ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x40;
152a1917f14Szrj ch->r_io[ATA_SERROR].offset = ch_offset + 0x44;
153a1917f14Szrj ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x48;
154a1917f14Szrj
155a1917f14Szrj ch->flags |= ATA_NO_SLAVE;
156a1917f14Szrj ata_pci_hw(dev);
15737c16061Szrj ch->hw.tf_read = ata_serverworks_tf_read;
15837c16061Szrj ch->hw.tf_write = ata_serverworks_tf_write;
159a1917f14Szrj
160a1917f14Szrj /* chip does not reliably do 64K DMA transfers */
161a1917f14Szrj if (ch->dma)
162878a3234Szrj ch->dma->max_iosize = 64 * DEV_BSIZE;
163a1917f14Szrj
164a1917f14Szrj return 0;
165a1917f14Szrj }
166a1917f14Szrj
167a1917f14Szrj static void
ata_serverworks_tf_read(struct ata_request * request)16837c16061Szrj ata_serverworks_tf_read(struct ata_request *request)
16937c16061Szrj {
17037c16061Szrj struct ata_channel *ch = device_get_softc(request->parent);
17137c16061Szrj struct ata_device *atadev = device_get_softc(request->dev);
17237c16061Szrj
17337c16061Szrj if (atadev->flags & ATA_D_48BIT_ACTIVE) {
17437c16061Szrj u_int16_t temp;
17537c16061Szrj
17637c16061Szrj request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT);
17737c16061Szrj temp = ATA_IDX_INW(ch, ATA_SECTOR);
17837c16061Szrj request->u.ata.lba = (u_int64_t)(temp & 0x00ff) |
17937c16061Szrj ((u_int64_t)(temp & 0xff00) << 24);
18037c16061Szrj temp = ATA_IDX_INW(ch, ATA_CYL_LSB);
18137c16061Szrj request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 8) |
18237c16061Szrj ((u_int64_t)(temp & 0xff00) << 32);
18337c16061Szrj temp = ATA_IDX_INW(ch, ATA_CYL_MSB);
18437c16061Szrj request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 16) |
18537c16061Szrj ((u_int64_t)(temp & 0xff00) << 40);
18637c16061Szrj }
18737c16061Szrj else {
18837c16061Szrj request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT) & 0x00ff;
18937c16061Szrj request->u.ata.lba = (ATA_IDX_INW(ch, ATA_SECTOR) & 0x00ff) |
19037c16061Szrj ((ATA_IDX_INW(ch, ATA_CYL_LSB) & 0x00ff) << 8) |
19137c16061Szrj ((ATA_IDX_INW(ch, ATA_CYL_MSB) & 0x00ff) << 16) |
19237c16061Szrj ((ATA_IDX_INW(ch, ATA_DRIVE) & 0xf) << 24);
19337c16061Szrj }
19437c16061Szrj }
19537c16061Szrj
19637c16061Szrj static void
ata_serverworks_tf_write(struct ata_request * request)19737c16061Szrj ata_serverworks_tf_write(struct ata_request *request)
19837c16061Szrj {
19937c16061Szrj struct ata_channel *ch = device_get_softc(request->parent);
20037c16061Szrj struct ata_device *atadev = device_get_softc(request->dev);
20137c16061Szrj
20237c16061Szrj if (atadev->flags & ATA_D_48BIT_ACTIVE) {
20337c16061Szrj ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
20437c16061Szrj ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
20537c16061Szrj ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |
20637c16061Szrj (request->u.ata.lba & 0x00ff));
20737c16061Szrj ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |
20837c16061Szrj ((request->u.ata.lba >> 8) & 0x00ff));
20937c16061Szrj ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) |
21037c16061Szrj ((request->u.ata.lba >> 16) & 0x00ff));
2112458a87aSzrj ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(atadev->unit));
21237c16061Szrj }
21337c16061Szrj else {
21437c16061Szrj ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
21537c16061Szrj ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
21637c16061Szrj if (atadev->flags & ATA_D_USE_CHS) {
21737c16061Szrj int heads, sectors;
21837c16061Szrj
21937c16061Szrj if (atadev->param.atavalid & ATA_FLAG_54_58) {
22037c16061Szrj heads = atadev->param.current_heads;
22137c16061Szrj sectors = atadev->param.current_sectors;
22237c16061Szrj }
22337c16061Szrj else {
22437c16061Szrj heads = atadev->param.heads;
22537c16061Szrj sectors = atadev->param.sectors;
22637c16061Szrj }
22737c16061Szrj
22837c16061Szrj ATA_IDX_OUTW(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
22937c16061Szrj ATA_IDX_OUTW(ch, ATA_CYL_LSB,
23037c16061Szrj (request->u.ata.lba / (sectors * heads)));
23137c16061Szrj ATA_IDX_OUTW(ch, ATA_CYL_MSB,
23237c16061Szrj (request->u.ata.lba / (sectors * heads)) >> 8);
2332458a87aSzrj ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(atadev->unit) |
23437c16061Szrj (((request->u.ata.lba% (sectors * heads)) /
23537c16061Szrj sectors) & 0xf));
23637c16061Szrj }
23737c16061Szrj else {
23837c16061Szrj ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba);
23937c16061Szrj ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
24037c16061Szrj ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
24137c16061Szrj ATA_IDX_OUTW(ch, ATA_DRIVE,
2422458a87aSzrj ATA_D_IBM | ATA_D_LBA | ATA_DEV(atadev->unit) |
24337c16061Szrj ((request->u.ata.lba >> 24) & 0x0f));
24437c16061Szrj }
24537c16061Szrj }
24637c16061Szrj }
24737c16061Szrj
24837c16061Szrj static void
ata_serverworks_setmode(device_t dev,int mode)249a1917f14Szrj ata_serverworks_setmode(device_t dev, int mode)
250a1917f14Szrj {
251a1917f14Szrj device_t gparent = GRANDPARENT(dev);
252a1917f14Szrj struct ata_pci_controller *ctlr = device_get_softc(gparent);
253a1917f14Szrj struct ata_channel *ch = device_get_softc(device_get_parent(dev));
254a1917f14Szrj struct ata_device *atadev = device_get_softc(dev);
2552458a87aSzrj int devno = (ch->unit << 1) + atadev->unit;
256a1917f14Szrj int offset = (devno ^ 0x01) << 3;
257a1917f14Szrj int error;
25859503772Szrj static const uint8_t piotimings[] =
25959503772Szrj { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
260a1917f14Szrj 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
26159503772Szrj static const uint8_t dmatimings[] = { 0x77, 0x21, 0x20 };
262a1917f14Szrj
263a1917f14Szrj mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
264a1917f14Szrj
265a1917f14Szrj mode = ata_check_80pin(dev, mode);
266a1917f14Szrj
267a1917f14Szrj error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
268a1917f14Szrj
269a1917f14Szrj if (bootverbose)
270a1917f14Szrj device_printf(dev, "%ssetting %s on %s chip\n",
271a1917f14Szrj (error) ? "FAILURE " : "",
272a1917f14Szrj ata_mode2str(mode), ctlr->chip->text);
273a1917f14Szrj if (!error) {
274a1917f14Szrj if (mode >= ATA_UDMA0) {
275a1917f14Szrj pci_write_config(gparent, 0x56,
276a1917f14Szrj (pci_read_config(gparent, 0x56, 2) &
277a1917f14Szrj ~(0xf << (devno << 2))) |
278a1917f14Szrj ((mode & ATA_MODE_MASK) << (devno << 2)), 2);
279a1917f14Szrj pci_write_config(gparent, 0x54,
280a1917f14Szrj pci_read_config(gparent, 0x54, 1) |
281a1917f14Szrj (0x01 << devno), 1);
282a1917f14Szrj pci_write_config(gparent, 0x44,
283a1917f14Szrj (pci_read_config(gparent, 0x44, 4) &
284a1917f14Szrj ~(0xff << offset)) |
285a1917f14Szrj (dmatimings[2] << offset), 4);
286a1917f14Szrj }
287a1917f14Szrj else if (mode >= ATA_WDMA0) {
288a1917f14Szrj pci_write_config(gparent, 0x54,
289a1917f14Szrj pci_read_config(gparent, 0x54, 1) &
290a1917f14Szrj ~(0x01 << devno), 1);
291a1917f14Szrj pci_write_config(gparent, 0x44,
292a1917f14Szrj (pci_read_config(gparent, 0x44, 4) &
293a1917f14Szrj ~(0xff << offset)) |
294a1917f14Szrj (dmatimings[mode & ATA_MODE_MASK] << offset), 4);
295a1917f14Szrj }
296a1917f14Szrj else
297a1917f14Szrj pci_write_config(gparent, 0x54,
298a1917f14Szrj pci_read_config(gparent, 0x54, 1) &
299a1917f14Szrj ~(0x01 << devno), 1);
300a1917f14Szrj
301a1917f14Szrj pci_write_config(gparent, 0x40,
302a1917f14Szrj (pci_read_config(gparent, 0x40, 4) &
303a1917f14Szrj ~(0xff << offset)) |
304a1917f14Szrj (piotimings[ata_mode2idx(mode)] << offset), 4);
305a1917f14Szrj atadev->mode = mode;
306a1917f14Szrj }
307a1917f14Szrj }
308