0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <linux/kernel.h>
0036 #include <linux/module.h>
0037 #include <linux/types.h>
0038 #include <linux/fcntl.h>
0039 #include <linux/gfp.h>
0040 #include <linux/interrupt.h>
0041 #include <linux/ioport.h>
0042 #include <linux/in.h>
0043 #include <linux/string.h>
0044 #include <linux/delay.h>
0045 #include <linux/nubus.h>
0046 #include <linux/errno.h>
0047 #include <linux/netdevice.h>
0048 #include <linux/etherdevice.h>
0049 #include <linux/skbuff.h>
0050 #include <linux/platform_device.h>
0051 #include <linux/dma-mapping.h>
0052 #include <linux/bitrev.h>
0053 #include <linux/slab.h>
0054 #include <linux/pgtable.h>
0055
0056 #include <asm/io.h>
0057 #include <asm/hwtest.h>
0058 #include <asm/dma.h>
0059 #include <asm/macintosh.h>
0060 #include <asm/macints.h>
0061 #include <asm/mac_via.h>
0062
0063 #include "sonic.h"
0064
0065
0066
0067
0068 #define SONIC_READ(reg) (nubus_readw(dev->base_addr + (reg * 4) \
0069 + lp->reg_offset))
0070 #define SONIC_WRITE(reg,val) (nubus_writew(val, dev->base_addr + (reg * 4) \
0071 + lp->reg_offset))
0072
0073
0074 #define ONBOARD_SONIC_REGISTERS 0x50F0A000
0075 #define ONBOARD_SONIC_PROM_BASE 0x50f08000
0076
0077 enum macsonic_type {
0078 MACSONIC_DUODOCK,
0079 MACSONIC_APPLE,
0080 MACSONIC_APPLE16,
0081 MACSONIC_DAYNA,
0082 MACSONIC_DAYNALINK
0083 };
0084
0085
0086 #define DUODOCK_SONIC_REGISTERS 0xe10000
0087 #define DUODOCK_SONIC_PROM_BASE 0xe12000
0088
0089
0090 #define APPLE_SONIC_REGISTERS 0
0091 #define APPLE_SONIC_PROM_BASE 0x40000
0092
0093
0094 #define DAYNALINK_PROM_BASE 0x400000
0095
0096
0097 #define DAYNA_SONIC_REGISTERS 0x180000
0098
0099
0100
0101 #define DAYNA_SONIC_MAC_ADDR 0xffe004
0102
0103 #define SONIC_READ_PROM(addr) nubus_readb(prom_addr+addr)
0104
0105
0106
0107
0108
0109 static inline void bit_reverse_addr(unsigned char addr[6])
0110 {
0111 int i;
0112
0113 for(i = 0; i < 6; i++)
0114 addr[i] = bitrev8(addr[i]);
0115 }
0116
0117 static int macsonic_open(struct net_device* dev)
0118 {
0119 int retval;
0120
0121 retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev);
0122 if (retval) {
0123 printk(KERN_ERR "%s: unable to get IRQ %d.\n",
0124 dev->name, dev->irq);
0125 goto err;
0126 }
0127
0128
0129
0130
0131 if (dev->irq == IRQ_AUTO_3) {
0132 retval = request_irq(IRQ_NUBUS_9, sonic_interrupt, 0,
0133 "sonic", dev);
0134 if (retval) {
0135 printk(KERN_ERR "%s: unable to get IRQ %d.\n",
0136 dev->name, IRQ_NUBUS_9);
0137 goto err_irq;
0138 }
0139 }
0140 retval = sonic_open(dev);
0141 if (retval)
0142 goto err_irq_nubus;
0143 return 0;
0144
0145 err_irq_nubus:
0146 if (dev->irq == IRQ_AUTO_3)
0147 free_irq(IRQ_NUBUS_9, dev);
0148 err_irq:
0149 free_irq(dev->irq, dev);
0150 err:
0151 return retval;
0152 }
0153
0154 static int macsonic_close(struct net_device* dev)
0155 {
0156 int err;
0157 err = sonic_close(dev);
0158 free_irq(dev->irq, dev);
0159 if (dev->irq == IRQ_AUTO_3)
0160 free_irq(IRQ_NUBUS_9, dev);
0161 return err;
0162 }
0163
0164 static const struct net_device_ops macsonic_netdev_ops = {
0165 .ndo_open = macsonic_open,
0166 .ndo_stop = macsonic_close,
0167 .ndo_start_xmit = sonic_send_packet,
0168 .ndo_set_rx_mode = sonic_multicast_list,
0169 .ndo_tx_timeout = sonic_tx_timeout,
0170 .ndo_get_stats = sonic_get_stats,
0171 .ndo_validate_addr = eth_validate_addr,
0172 .ndo_set_mac_address = eth_mac_addr,
0173 };
0174
0175 static int macsonic_init(struct net_device *dev)
0176 {
0177 struct sonic_local* lp = netdev_priv(dev);
0178 int err = sonic_alloc_descriptors(dev);
0179
0180 if (err)
0181 return err;
0182
0183 dev->netdev_ops = &macsonic_netdev_ops;
0184 dev->watchdog_timeo = TX_TIMEOUT;
0185
0186
0187
0188
0189 SONIC_WRITE(SONIC_CRCT, 0xffff);
0190 SONIC_WRITE(SONIC_FAET, 0xffff);
0191 SONIC_WRITE(SONIC_MPT, 0xffff);
0192
0193 return 0;
0194 }
0195
0196 #define INVALID_MAC(mac) (memcmp(mac, "\x08\x00\x07", 3) && \
0197 memcmp(mac, "\x00\xA0\x40", 3) && \
0198 memcmp(mac, "\x00\x80\x19", 3) && \
0199 memcmp(mac, "\x00\x05\x02", 3))
0200
0201 static void mac_onboard_sonic_ethernet_addr(struct net_device *dev)
0202 {
0203 struct sonic_local *lp = netdev_priv(dev);
0204 const int prom_addr = ONBOARD_SONIC_PROM_BASE;
0205 unsigned short val;
0206 u8 addr[ETH_ALEN];
0207
0208
0209
0210
0211
0212
0213 if (hwreg_present((void *)prom_addr)) {
0214 int i;
0215
0216 for (i = 0; i < 6; i++)
0217 addr[i] = SONIC_READ_PROM(i);
0218 eth_hw_addr_set(dev, addr);
0219 if (!INVALID_MAC(dev->dev_addr))
0220 return;
0221
0222
0223
0224
0225
0226
0227 bit_reverse_addr(addr);
0228 eth_hw_addr_set(dev, addr);
0229 if (!INVALID_MAC(dev->dev_addr))
0230 return;
0231
0232
0233
0234
0235
0236 printk(KERN_WARNING "macsonic: MAC address in PROM seems "
0237 "to be invalid, trying CAM\n");
0238 } else {
0239 printk(KERN_WARNING "macsonic: cannot read MAC address from "
0240 "PROM, trying CAM\n");
0241 }
0242
0243
0244
0245 SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
0246 SONIC_WRITE(SONIC_CEP, 15);
0247
0248 val = SONIC_READ(SONIC_CAP2);
0249 addr[5] = val >> 8;
0250 addr[4] = val & 0xff;
0251 val = SONIC_READ(SONIC_CAP1);
0252 addr[3] = val >> 8;
0253 addr[2] = val & 0xff;
0254 val = SONIC_READ(SONIC_CAP0);
0255 addr[1] = val >> 8;
0256 addr[0] = val & 0xff;
0257 eth_hw_addr_set(dev, addr);
0258
0259 if (!INVALID_MAC(dev->dev_addr))
0260 return;
0261
0262
0263
0264 printk(KERN_WARNING "macsonic: MAC address in CAM entry 15 "
0265 "seems invalid, will use a random MAC\n");
0266 eth_hw_addr_random(dev);
0267 }
0268
0269 static int mac_onboard_sonic_probe(struct net_device *dev)
0270 {
0271 struct sonic_local* lp = netdev_priv(dev);
0272 int sr;
0273 bool commslot = macintosh_config->expansion_type == MAC_EXP_PDS_COMM;
0274
0275
0276
0277
0278
0279 if (commslot || macintosh_config->ident == MAC_MODEL_C610) {
0280 int card_present;
0281
0282 card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS);
0283 if (!card_present) {
0284 pr_info("Onboard/comm-slot SONIC not found\n");
0285 return -ENODEV;
0286 }
0287 }
0288
0289
0290
0291 dev->base_addr = ONBOARD_SONIC_REGISTERS;
0292 if (via_alt_mapping)
0293 dev->irq = IRQ_AUTO_3;
0294 else
0295 dev->irq = IRQ_NUBUS_9;
0296
0297
0298 if (macintosh_config->ident == MAC_MODEL_PB520) {
0299 lp->reg_offset = 0;
0300 lp->dma_bitmode = SONIC_BITMODE16;
0301 } else if (commslot) {
0302
0303
0304
0305
0306
0307 lp->reg_offset = 2;
0308 lp->dma_bitmode = SONIC_BITMODE16;
0309
0310 sr = SONIC_READ(SONIC_SR);
0311 if (sr == 0x0004 || sr == 0x0006 || sr == 0x0100 || sr == 0x0101)
0312
0313 lp->dma_bitmode = SONIC_BITMODE32;
0314 else {
0315 lp->dma_bitmode = SONIC_BITMODE16;
0316 lp->reg_offset = 0;
0317 }
0318 } else {
0319
0320 lp->reg_offset = 2;
0321 lp->dma_bitmode = SONIC_BITMODE32;
0322 }
0323
0324 pr_info("Onboard/comm-slot SONIC, revision 0x%04x, %d bit DMA, register offset %d\n",
0325 SONIC_READ(SONIC_SR), lp->dma_bitmode ? 32 : 16,
0326 lp->reg_offset);
0327
0328
0329 pr_debug("%s: DCR=0x%04x, DCR2=0x%04x\n", __func__,
0330 SONIC_READ(SONIC_DCR) & 0xffff,
0331 SONIC_READ(SONIC_DCR2) & 0xffff);
0332
0333
0334 SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
0335
0336 SONIC_WRITE(SONIC_DCR, SONIC_DCR_EXBUS | SONIC_DCR_BMS |
0337 SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
0338 (lp->dma_bitmode ? SONIC_DCR_DW : 0));
0339
0340
0341
0342
0343 SONIC_WRITE(SONIC_DCR2, 0);
0344
0345
0346 SONIC_WRITE(SONIC_IMR, 0);
0347 SONIC_WRITE(SONIC_ISR, 0x7fff);
0348
0349
0350 mac_onboard_sonic_ethernet_addr(dev);
0351
0352 pr_info("SONIC ethernet @%08lx, MAC %pM, IRQ %d\n",
0353 dev->base_addr, dev->dev_addr, dev->irq);
0354
0355
0356 return macsonic_init(dev);
0357 }
0358
0359 static int mac_sonic_nubus_ethernet_addr(struct net_device *dev,
0360 unsigned long prom_addr, int id)
0361 {
0362 u8 addr[ETH_ALEN];
0363 int i;
0364
0365 for(i = 0; i < 6; i++)
0366 addr[i] = SONIC_READ_PROM(i);
0367
0368
0369 if (id != MACSONIC_DAYNA)
0370 bit_reverse_addr(addr);
0371 eth_hw_addr_set(dev, addr);
0372
0373 return 0;
0374 }
0375
0376 static int macsonic_ident(struct nubus_rsrc *fres)
0377 {
0378 if (fres->dr_hw == NUBUS_DRHW_ASANTE_LC &&
0379 fres->dr_sw == NUBUS_DRSW_SONIC_LC)
0380 return MACSONIC_DAYNALINK;
0381 if (fres->dr_hw == NUBUS_DRHW_SONIC &&
0382 fres->dr_sw == NUBUS_DRSW_APPLE) {
0383
0384 if (strstr(fres->board->name, "DuoDock"))
0385 return MACSONIC_DUODOCK;
0386 else
0387 return MACSONIC_APPLE;
0388 }
0389
0390 if (fres->dr_hw == NUBUS_DRHW_SMC9194 &&
0391 fres->dr_sw == NUBUS_DRSW_DAYNA)
0392 return MACSONIC_DAYNA;
0393
0394 if (fres->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC &&
0395 fres->dr_sw == 0) {
0396 return MACSONIC_APPLE16;
0397 }
0398 return -1;
0399 }
0400
0401 static int mac_sonic_nubus_probe_board(struct nubus_board *board, int id,
0402 struct net_device *dev)
0403 {
0404 struct sonic_local* lp = netdev_priv(dev);
0405 unsigned long base_addr, prom_addr;
0406 u16 sonic_dcr;
0407 int reg_offset, dma_bitmode;
0408
0409 switch (id) {
0410 case MACSONIC_DUODOCK:
0411 base_addr = board->slot_addr + DUODOCK_SONIC_REGISTERS;
0412 prom_addr = board->slot_addr + DUODOCK_SONIC_PROM_BASE;
0413 sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1 |
0414 SONIC_DCR_TFT0;
0415 reg_offset = 2;
0416 dma_bitmode = SONIC_BITMODE32;
0417 break;
0418 case MACSONIC_APPLE:
0419 base_addr = board->slot_addr + APPLE_SONIC_REGISTERS;
0420 prom_addr = board->slot_addr + APPLE_SONIC_PROM_BASE;
0421 sonic_dcr = SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0;
0422 reg_offset = 0;
0423 dma_bitmode = SONIC_BITMODE32;
0424 break;
0425 case MACSONIC_APPLE16:
0426 base_addr = board->slot_addr + APPLE_SONIC_REGISTERS;
0427 prom_addr = board->slot_addr + APPLE_SONIC_PROM_BASE;
0428 sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
0429 SONIC_DCR_PO1 | SONIC_DCR_BMS;
0430 reg_offset = 0;
0431 dma_bitmode = SONIC_BITMODE16;
0432 break;
0433 case MACSONIC_DAYNALINK:
0434 base_addr = board->slot_addr + APPLE_SONIC_REGISTERS;
0435 prom_addr = board->slot_addr + DAYNALINK_PROM_BASE;
0436 sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0 |
0437 SONIC_DCR_PO1 | SONIC_DCR_BMS;
0438 reg_offset = 0;
0439 dma_bitmode = SONIC_BITMODE16;
0440 break;
0441 case MACSONIC_DAYNA:
0442 base_addr = board->slot_addr + DAYNA_SONIC_REGISTERS;
0443 prom_addr = board->slot_addr + DAYNA_SONIC_MAC_ADDR;
0444 sonic_dcr = SONIC_DCR_BMS |
0445 SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
0446 reg_offset = 0;
0447 dma_bitmode = SONIC_BITMODE16;
0448 break;
0449 default:
0450 printk(KERN_ERR "macsonic: WTF, id is %d\n", id);
0451 return -ENODEV;
0452 }
0453
0454
0455
0456 dev->base_addr = base_addr;
0457 lp->reg_offset = reg_offset;
0458 lp->dma_bitmode = dma_bitmode;
0459 dev->irq = SLOT2IRQ(board->slot);
0460
0461 dev_info(&board->dev, "%s, revision 0x%04x, %d bit DMA, register offset %d\n",
0462 board->name, SONIC_READ(SONIC_SR),
0463 lp->dma_bitmode ? 32 : 16, lp->reg_offset);
0464
0465
0466 dev_dbg(&board->dev, "%s: DCR=0x%04x, DCR2=0x%04x\n", __func__,
0467 SONIC_READ(SONIC_DCR) & 0xffff,
0468 SONIC_READ(SONIC_DCR2) & 0xffff);
0469
0470
0471 SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
0472 SONIC_WRITE(SONIC_DCR, sonic_dcr | (dma_bitmode ? SONIC_DCR_DW : 0));
0473
0474
0475
0476 SONIC_WRITE(SONIC_DCR2, 0);
0477
0478
0479 SONIC_WRITE(SONIC_IMR, 0);
0480 SONIC_WRITE(SONIC_ISR, 0x7fff);
0481
0482
0483 if (mac_sonic_nubus_ethernet_addr(dev, prom_addr, id) != 0)
0484 return -ENODEV;
0485
0486 dev_info(&board->dev, "SONIC ethernet @%08lx, MAC %pM, IRQ %d\n",
0487 dev->base_addr, dev->dev_addr, dev->irq);
0488
0489
0490 return macsonic_init(dev);
0491 }
0492
0493 static int mac_sonic_platform_probe(struct platform_device *pdev)
0494 {
0495 struct net_device *dev;
0496 struct sonic_local *lp;
0497 int err;
0498
0499 dev = alloc_etherdev(sizeof(struct sonic_local));
0500 if (!dev)
0501 return -ENOMEM;
0502
0503 lp = netdev_priv(dev);
0504 lp->device = &pdev->dev;
0505 SET_NETDEV_DEV(dev, &pdev->dev);
0506 platform_set_drvdata(pdev, dev);
0507
0508 err = mac_onboard_sonic_probe(dev);
0509 if (err)
0510 goto out;
0511
0512 sonic_msg_init(dev);
0513
0514 err = register_netdev(dev);
0515 if (err)
0516 goto undo_probe;
0517
0518 return 0;
0519
0520 undo_probe:
0521 dma_free_coherent(lp->device,
0522 SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
0523 lp->descriptors, lp->descriptors_laddr);
0524 out:
0525 free_netdev(dev);
0526
0527 return err;
0528 }
0529
0530 MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
0531 MODULE_ALIAS("platform:macsonic");
0532
0533 #include "sonic.c"
0534
0535 static int mac_sonic_platform_remove(struct platform_device *pdev)
0536 {
0537 struct net_device *dev = platform_get_drvdata(pdev);
0538 struct sonic_local* lp = netdev_priv(dev);
0539
0540 unregister_netdev(dev);
0541 dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
0542 lp->descriptors, lp->descriptors_laddr);
0543 free_netdev(dev);
0544
0545 return 0;
0546 }
0547
0548 static struct platform_driver mac_sonic_platform_driver = {
0549 .probe = mac_sonic_platform_probe,
0550 .remove = mac_sonic_platform_remove,
0551 .driver = {
0552 .name = "macsonic",
0553 },
0554 };
0555
0556 static int mac_sonic_nubus_probe(struct nubus_board *board)
0557 {
0558 struct net_device *ndev;
0559 struct sonic_local *lp;
0560 struct nubus_rsrc *fres;
0561 int id = -1;
0562 int err;
0563
0564
0565
0566
0567 if (macintosh_config->expansion_type == MAC_EXP_PDS_COMM)
0568 return -ENODEV;
0569
0570 for_each_board_func_rsrc(board, fres) {
0571 if (fres->category != NUBUS_CAT_NETWORK ||
0572 fres->type != NUBUS_TYPE_ETHERNET)
0573 continue;
0574
0575 id = macsonic_ident(fres);
0576 if (id != -1)
0577 break;
0578 }
0579 if (!fres)
0580 return -ENODEV;
0581
0582 ndev = alloc_etherdev(sizeof(struct sonic_local));
0583 if (!ndev)
0584 return -ENOMEM;
0585
0586 lp = netdev_priv(ndev);
0587 lp->device = &board->dev;
0588 SET_NETDEV_DEV(ndev, &board->dev);
0589
0590 err = mac_sonic_nubus_probe_board(board, id, ndev);
0591 if (err)
0592 goto out;
0593
0594 sonic_msg_init(ndev);
0595
0596 err = register_netdev(ndev);
0597 if (err)
0598 goto undo_probe;
0599
0600 nubus_set_drvdata(board, ndev);
0601
0602 return 0;
0603
0604 undo_probe:
0605 dma_free_coherent(lp->device,
0606 SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
0607 lp->descriptors, lp->descriptors_laddr);
0608 out:
0609 free_netdev(ndev);
0610 return err;
0611 }
0612
0613 static void mac_sonic_nubus_remove(struct nubus_board *board)
0614 {
0615 struct net_device *ndev = nubus_get_drvdata(board);
0616 struct sonic_local *lp = netdev_priv(ndev);
0617
0618 unregister_netdev(ndev);
0619 dma_free_coherent(lp->device,
0620 SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
0621 lp->descriptors, lp->descriptors_laddr);
0622 free_netdev(ndev);
0623 }
0624
0625 static struct nubus_driver mac_sonic_nubus_driver = {
0626 .probe = mac_sonic_nubus_probe,
0627 .remove = mac_sonic_nubus_remove,
0628 .driver = {
0629 .name = "macsonic-nubus",
0630 .owner = THIS_MODULE,
0631 },
0632 };
0633
0634 static int perr, nerr;
0635
0636 static int __init mac_sonic_init(void)
0637 {
0638 perr = platform_driver_register(&mac_sonic_platform_driver);
0639 nerr = nubus_driver_register(&mac_sonic_nubus_driver);
0640 return 0;
0641 }
0642 module_init(mac_sonic_init);
0643
0644 static void __exit mac_sonic_exit(void)
0645 {
0646 if (!perr)
0647 platform_driver_unregister(&mac_sonic_platform_driver);
0648 if (!nerr)
0649 nubus_driver_unregister(&mac_sonic_nubus_driver);
0650 }
0651 module_exit(mac_sonic_exit);