xref: /dflybsd-src/sys/dev/disk/nata/chipsets/ata-serverworks.c (revision 07c11d3bea335f92e71e16bd1faa191777392a04)
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